npm-anthropic-ai--sdk

Description
The official TypeScript library for the Anthropic API providing comprehensive client functionality for Claude AI models.
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/npm-anthropic-ai--sdk@0.61.0

error-handling.md docs/

1
# Error Handling
2
3
The Anthropic SDK provides a comprehensive error hierarchy for handling different types of API failures, network issues, and client-side problems. All errors extend the base `AnthropicError` class and include detailed information for debugging and recovery.
4
5
## Capabilities
6
7
### Error Hierarchy
8
9
Comprehensive error types covering all aspects of API interaction and client behavior.
10
11
```typescript { .api }
12
/**
13
* Base error class for all Anthropic SDK errors
14
*/
15
class AnthropicError extends Error {
16
/** Error name */
17
name: string;
18
/** Error message */
19
message: string;
20
/** Error cause (if available) */
21
cause?: unknown;
22
}
23
24
/**
25
* Base class for API-related errors
26
*/
27
class APIError extends AnthropicError {
28
/** HTTP status code */
29
status: number;
30
/** Response headers */
31
headers: Headers;
32
/** Error details from API response */
33
error?: APIErrorObject;
34
/** Request that caused the error */
35
request?: Request;
36
}
37
38
interface APIErrorObject {
39
/** Error type identifier */
40
type: string;
41
/** Human-readable error message */
42
message: string;
43
}
44
```
45
46
### HTTP Status Error Types
47
48
Specific error classes for different HTTP status codes with targeted handling strategies.
49
50
```typescript { .api }
51
/**
52
* 400 Bad Request - Invalid request parameters
53
*/
54
class BadRequestError extends APIError {
55
status: 400;
56
}
57
58
/**
59
* 401 Unauthorized - Authentication failure
60
*/
61
class AuthenticationError extends APIError {
62
status: 401;
63
}
64
65
/**
66
* 403 Forbidden - Insufficient permissions
67
*/
68
class PermissionDeniedError extends APIError {
69
status: 403;
70
}
71
72
/**
73
* 404 Not Found - Resource not found
74
*/
75
class NotFoundError extends APIError {
76
status: 404;
77
}
78
79
/**
80
* 409 Conflict - Request conflicts with current state
81
*/
82
class ConflictError extends APIError {
83
status: 409;
84
}
85
86
/**
87
* 422 Unprocessable Entity - Valid request but server cannot process
88
*/
89
class UnprocessableEntityError extends APIError {
90
status: 422;
91
}
92
93
/**
94
* 429 Too Many Requests - Rate limit exceeded
95
*/
96
class RateLimitError extends APIError {
97
status: 429;
98
}
99
100
/**
101
* 500 Internal Server Error - Server-side error
102
*/
103
class InternalServerError extends APIError {
104
status: 500;
105
}
106
```
107
108
### Connection Error Types
109
110
Errors related to network connectivity and request lifecycle.
111
112
```typescript { .api }
113
/**
114
* Network connection failed
115
*/
116
class APIConnectionError extends AnthropicError {
117
/** Underlying network error */
118
cause: Error;
119
}
120
121
/**
122
* Request timed out
123
*/
124
class APIConnectionTimeoutError extends APIConnectionError {
125
/** Timeout duration in milliseconds */
126
timeout: number;
127
}
128
129
/**
130
* Request was aborted by user
131
*/
132
class APIUserAbortError extends APIConnectionError {
133
/** Abort signal that triggered the error */
134
signal: AbortSignal;
135
}
136
```
137
138
## Error Handling Patterns
139
140
### Basic Error Handling
141
142
Handle common API errors with appropriate recovery strategies.
143
144
**Usage Examples:**
145
146
```typescript
147
import Anthropic, {
148
AnthropicError,
149
AuthenticationError,
150
RateLimitError,
151
BadRequestError,
152
APIConnectionError
153
} from "@anthropic-ai/sdk";
154
155
const client = new Anthropic();
156
157
try {
158
const message = await client.messages.create({
159
model: "claude-3-sonnet-20240229",
160
max_tokens: 1024,
161
messages: [{ role: "user", content: "Hello!" }],
162
});
163
} catch (error) {
164
if (error instanceof AuthenticationError) {
165
console.error("Authentication failed - check your API key");
166
// Redirect to authentication setup
167
} else if (error instanceof RateLimitError) {
168
console.error("Rate limit exceeded - implementing backoff");
169
// Implement exponential backoff retry
170
await sleep(5000);
171
// Retry the request
172
} else if (error instanceof BadRequestError) {
173
console.error("Invalid request parameters:", error.message);
174
// Fix request parameters and retry
175
} else if (error instanceof APIConnectionError) {
176
console.error("Network connection failed:", error.cause);
177
// Check network connectivity, retry with timeout
178
} else if (error instanceof AnthropicError) {
179
console.error("Anthropic SDK error:", error.message);
180
// Handle other SDK-specific errors
181
} else {
182
console.error("Unexpected error:", error);
183
// Handle unexpected errors
184
}
185
}
186
```
187
188
### Rate Limit Handling
189
190
Implement sophisticated rate limit handling with exponential backoff.
191
192
```typescript { .api }
193
/**
194
* Rate limit error with retry information
195
*/
196
interface RateLimitInfo {
197
/** Requests per minute limit */
198
limit: number;
199
/** Remaining requests in current window */
200
remaining: number;
201
/** Time when rate limit resets (Unix timestamp) */
202
reset: number;
203
/** Recommended retry delay in seconds */
204
retryAfter?: number;
205
}
206
```
207
208
**Usage Examples:**
209
210
```typescript
211
async function withRateLimitRetry<T>(
212
operation: () => Promise<T>,
213
maxRetries: number = 3
214
): Promise<T> {
215
let attempt = 0;
216
217
while (attempt < maxRetries) {
218
try {
219
return await operation();
220
} catch (error) {
221
if (error instanceof RateLimitError) {
222
const retryAfter = error.headers.get("retry-after");
223
const delay = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000;
224
225
console.log(`Rate limited. Retrying in ${delay}ms...`);
226
await sleep(delay);
227
attempt++;
228
} else {
229
throw error; // Re-throw non-rate-limit errors
230
}
231
}
232
}
233
234
throw new Error(`Max retries (${maxRetries}) exceeded for rate-limited request`);
235
}
236
237
// Usage
238
const message = await withRateLimitRetry(() =>
239
client.messages.create({
240
model: "claude-3-sonnet-20240229",
241
max_tokens: 1024,
242
messages: [{ role: "user", content: "Hello!" }],
243
})
244
);
245
```
246
247
### Timeout and Abort Handling
248
249
Handle request timeouts and user-initiated cancellations.
250
251
**Usage Examples:**
252
253
```typescript
254
// Request with custom timeout
255
const controller = new AbortController();
256
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
257
258
try {
259
const message = await client.messages.create(
260
{
261
model: "claude-3-sonnet-20240229",
262
max_tokens: 1024,
263
messages: [{ role: "user", content: "Complex task..." }],
264
},
265
{
266
fetchOptions: { signal: controller.signal },
267
timeout: 30000,
268
}
269
);
270
clearTimeout(timeoutId);
271
} catch (error) {
272
if (error instanceof APIUserAbortError) {
273
console.log("Request was cancelled by user");
274
} else if (error instanceof APIConnectionTimeoutError) {
275
console.log(`Request timed out after ${error.timeout}ms`);
276
// Retry with longer timeout or different strategy
277
}
278
}
279
280
// Streaming with cancellation
281
const stream = client.messages.stream({
282
model: "claude-3-sonnet-20240229",
283
max_tokens: 1024,
284
messages: [{ role: "user", content: "Long response..." }],
285
});
286
287
// Cancel stream after user action
288
document.getElementById("cancel").onclick = () => {
289
stream.controller.abort();
290
};
291
292
try {
293
for await (const event of stream) {
294
console.log(event);
295
}
296
} catch (error) {
297
if (error instanceof APIUserAbortError) {
298
console.log("Stream cancelled by user");
299
}
300
}
301
```
302
303
### Validation Error Handling
304
305
Handle parameter validation and request formatting errors.
306
307
**Usage Examples:**
308
309
```typescript
310
try {
311
const message = await client.messages.create({
312
model: "claude-3-sonnet-20240229",
313
max_tokens: -1, // Invalid parameter
314
messages: [], // Empty messages array
315
});
316
} catch (error) {
317
if (error instanceof BadRequestError) {
318
console.error("Request validation failed:");
319
console.error("Status:", error.status);
320
console.error("Message:", error.message);
321
322
if (error.error) {
323
console.error("Error type:", error.error.type);
324
console.error("Details:", error.error.message);
325
}
326
327
// Fix validation issues
328
const validMessage = await client.messages.create({
329
model: "claude-3-sonnet-20240229",
330
max_tokens: 1024, // Valid parameter
331
messages: [{ role: "user", content: "Valid message" }], // Valid messages
332
});
333
}
334
}
335
```
336
337
### Beta Error Handling
338
339
Handle beta-specific errors and feature availability issues.
340
341
```typescript { .api }
342
/**
343
* Beta-specific error types
344
*/
345
class BetaError extends AnthropicError {}
346
class BetaAPIError extends BetaError {
347
status: number;
348
error: BetaErrorResponse;
349
}
350
class BetaInvalidRequestError extends BetaAPIError {}
351
class BetaNotFoundError extends BetaAPIError {}
352
class BetaPermissionError extends BetaAPIError {}
353
354
interface BetaErrorResponse {
355
type: string;
356
message: string;
357
}
358
```
359
360
**Usage Examples:**
361
362
```typescript
363
import { BetaError, BetaPermissionError } from "@anthropic-ai/sdk";
364
365
try {
366
const betaResult = await client.beta.messages.create({
367
model: "claude-3-5-sonnet-20241022",
368
max_tokens: 1024,
369
messages: [{ role: "user", content: "Beta feature test" }],
370
betas: ["experimental-feature-2024"],
371
});
372
} catch (error) {
373
if (error instanceof BetaPermissionError) {
374
console.error("No access to beta feature - request access");
375
// Fall back to stable API
376
return client.messages.create({
377
model: "claude-3-sonnet-20240229",
378
max_tokens: 1024,
379
messages: [{ role: "user", content: "Beta feature test" }],
380
});
381
} else if (error instanceof BetaError) {
382
console.error("Beta feature error:", error.message);
383
// Handle beta-specific issues
384
}
385
}
386
```
387
388
## Error Context and Debugging
389
390
### Error Information Access
391
392
Extract detailed information from errors for debugging and logging.
393
394
**Usage Examples:**
395
396
```typescript
397
try {
398
const message = await client.messages.create(params);
399
} catch (error) {
400
if (error instanceof APIError) {
401
// Log comprehensive error details
402
console.error("API Error Details:", {
403
status: error.status,
404
message: error.message,
405
type: error.error?.type,
406
headers: Object.fromEntries(error.headers.entries()),
407
requestId: error.headers.get("request-id"),
408
});
409
410
// Access raw response for debugging
411
if (error.request) {
412
console.error("Request URL:", error.request.url);
413
console.error("Request Method:", error.request.method);
414
}
415
}
416
}
417
```
418
419
### Custom Error Handling
420
421
Create custom error handlers and recovery strategies.
422
423
**Usage Examples:**
424
425
```typescript
426
class AnthropicAPIHandler {
427
private client: Anthropic;
428
private retryConfig: RetryConfig;
429
430
constructor(client: Anthropic, retryConfig: RetryConfig = {}) {
431
this.client = client;
432
this.retryConfig = { maxRetries: 3, baseDelay: 1000, ...retryConfig };
433
}
434
435
async createMessage(params: MessageCreateParams): Promise<Message> {
436
return this.withErrorHandling(() =>
437
this.client.messages.create(params)
438
);
439
}
440
441
private async withErrorHandling<T>(operation: () => Promise<T>): Promise<T> {
442
let lastError: Error;
443
444
for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {
445
try {
446
return await operation();
447
} catch (error) {
448
lastError = error;
449
450
if (this.shouldRetry(error, attempt)) {
451
const delay = this.calculateDelay(attempt);
452
await this.sleep(delay);
453
continue;
454
}
455
456
throw this.enrichError(error);
457
}
458
}
459
460
throw lastError;
461
}
462
463
private shouldRetry(error: unknown, attempt: number): boolean {
464
if (attempt >= this.retryConfig.maxRetries) return false;
465
466
return error instanceof RateLimitError ||
467
error instanceof APIConnectionTimeoutError ||
468
error instanceof InternalServerError;
469
}
470
471
private calculateDelay(attempt: number): number {
472
return this.retryConfig.baseDelay * Math.pow(2, attempt);
473
}
474
475
private enrichError(error: unknown): Error {
476
if (error instanceof APIError) {
477
const enriched = new Error(
478
`Anthropic API Error: ${error.message} (Status: ${error.status})`
479
);
480
enriched.cause = error;
481
return enriched;
482
}
483
484
return error instanceof Error ? error : new Error(String(error));
485
}
486
487
private sleep(ms: number): Promise<void> {
488
return new Promise(resolve => setTimeout(resolve, ms));
489
}
490
}
491
492
interface RetryConfig {
493
maxRetries?: number;
494
baseDelay?: number;
495
}
496
```
497
498
## Error Prevention
499
500
### Input Validation
501
502
Validate parameters before making API calls to prevent common errors.
503
504
**Usage Examples:**
505
506
```typescript
507
function validateMessageParams(params: MessageCreateParams): void {
508
if (!params.model) {
509
throw new Error("Model is required");
510
}
511
512
if (!params.messages || params.messages.length === 0) {
513
throw new Error("At least one message is required");
514
}
515
516
if (params.max_tokens <= 0) {
517
throw new Error("max_tokens must be positive");
518
}
519
520
if (params.temperature !== undefined && (params.temperature < 0 || params.temperature > 1)) {
521
throw new Error("temperature must be between 0 and 1");
522
}
523
}
524
525
// Usage
526
try {
527
validateMessageParams(messageParams);
528
const message = await client.messages.create(messageParams);
529
} catch (error) {
530
console.error("Validation error:", error.message);
531
}
532
```
533
534
### Health Checks
535
536
Implement health checks to verify API connectivity and authentication.
537
538
**Usage Examples:**
539
540
```typescript
541
async function checkAPIHealth(client: Anthropic): Promise<boolean> {
542
try {
543
await client.models.list({ limit: 1 });
544
return true;
545
} catch (error) {
546
if (error instanceof AuthenticationError) {
547
console.error("Authentication failed - check API key");
548
} else if (error instanceof APIConnectionError) {
549
console.error("Connection failed - check network");
550
}
551
return false;
552
}
553
}
554
555
// Usage
556
if (await checkAPIHealth(client)) {
557
console.log("API is healthy");
558
} else {
559
console.log("API health check failed");
560
}
561
```