0
# Error Handling
1
2
Comprehensive exception handling for the Anthropic Python SDK. All exceptions inherit from `AnthropicError` and provide detailed error information including HTTP status codes, request IDs, and response bodies.
3
4
## Exception Hierarchy
5
6
```
7
AnthropicError (Base exception for all SDK errors)
8
├── APIError (Base for API-related errors)
9
│ ├── APIConnectionError (Connection failures)
10
│ │ └── APITimeoutError (Request timeouts)
11
│ ├── APIResponseValidationError (Response validation failures)
12
│ └── APIStatusError (HTTP status errors)
13
│ ├── BadRequestError (400)
14
│ ├── AuthenticationError (401)
15
│ ├── PermissionDeniedError (403)
16
│ ├── NotFoundError (404)
17
│ ├── ConflictError (409)
18
│ ├── RequestTooLargeError (413)
19
│ ├── UnprocessableEntityError (422)
20
│ ├── RateLimitError (429)
21
│ ├── ServiceUnavailableError (503)
22
│ ├── DeadlineExceededError (504)
23
│ ├── OverloadedError (529)
24
│ └── InternalServerError (5xx)
25
```
26
27
## Base Exceptions
28
29
### AnthropicError
30
31
```python { .api }
32
class AnthropicError(Exception):
33
"""
34
Base exception for all Anthropic SDK errors.
35
36
All other exceptions inherit from this base class.
37
"""
38
```
39
40
**Usage:**
41
42
```python
43
import anthropic
44
from anthropic import AnthropicError
45
46
client = anthropic.Anthropic(api_key="your-api-key")
47
48
try:
49
message = client.messages.create(
50
model="claude-3-5-sonnet-20241022",
51
max_tokens=1024,
52
messages=[{"role": "user", "content": "Hello!"}]
53
)
54
except AnthropicError as e:
55
# Catches all SDK exceptions
56
print(f"An error occurred: {e}")
57
```
58
59
### APIError
60
61
```python { .api }
62
class APIError(AnthropicError):
63
"""
64
Base exception for API-related errors.
65
66
Contains request and response information.
67
"""
68
69
message: str
70
"""Error message describing what went wrong"""
71
72
request: httpx.Request
73
"""The HTTP request object that triggered the error"""
74
75
body: object | None
76
"""
77
The API response body.
78
79
If the API responded with valid JSON, this will be the decoded result.
80
If it isn't valid JSON, this will be the raw response text.
81
If there was no response, this will be None.
82
"""
83
84
def __init__(
85
self,
86
message: str,
87
request: httpx.Request,
88
*,
89
body: object | None
90
) -> None: ...
91
```
92
93
**Usage:**
94
95
```python
96
import anthropic
97
from anthropic import APIError
98
99
client = anthropic.Anthropic(api_key="your-api-key")
100
101
try:
102
message = client.messages.create(
103
model="claude-3-5-sonnet-20241022",
104
max_tokens=1024,
105
messages=[{"role": "user", "content": "Hello!"}]
106
)
107
except APIError as e:
108
print(f"API Error: {e.message}")
109
print(f"Request URL: {e.request.url}")
110
if e.body:
111
print(f"Response body: {e.body}")
112
```
113
114
## HTTP Status Errors
115
116
### APIStatusError
117
118
```python { .api }
119
class APIStatusError(APIError):
120
"""
121
Base exception for HTTP status errors (4xx and 5xx responses).
122
123
Raised when the API returns an error status code.
124
"""
125
126
response: httpx.Response
127
"""The HTTP response object"""
128
129
status_code: int
130
"""HTTP status code (e.g., 400, 401, 429, 500)"""
131
132
request_id: str | None
133
"""
134
Request ID from response headers for debugging.
135
136
Available in the 'request-id' header. Useful when contacting support.
137
"""
138
139
def __init__(
140
self,
141
message: str,
142
*,
143
response: httpx.Response,
144
body: object | None
145
) -> None: ...
146
```
147
148
**Usage:**
149
150
```python
151
import anthropic
152
from anthropic import APIStatusError
153
154
client = anthropic.Anthropic(api_key="your-api-key")
155
156
try:
157
message = client.messages.create(
158
model="claude-3-5-sonnet-20241022",
159
max_tokens=1024,
160
messages=[{"role": "user", "content": "Hello!"}]
161
)
162
except APIStatusError as e:
163
print(f"HTTP {e.status_code}: {e.message}")
164
print(f"Request ID: {e.request_id}")
165
print(f"Response headers: {dict(e.response.headers)}")
166
```
167
168
### BadRequestError (400)
169
170
```python { .api }
171
class BadRequestError(APIStatusError):
172
"""
173
400 Bad Request error.
174
175
Raised when the request is malformed or contains invalid parameters.
176
"""
177
178
status_code: Literal[400] = 400
179
```
180
181
**Common Causes:**
182
183
- Invalid JSON in request body
184
- Missing required parameters
185
- Invalid parameter values
186
- Malformed message format
187
188
**Example:**
189
190
```python
191
import anthropic
192
from anthropic import BadRequestError
193
194
client = anthropic.Anthropic(api_key="your-api-key")
195
196
try:
197
# Missing required 'messages' parameter
198
message = client.messages.create(
199
model="claude-3-5-sonnet-20241022",
200
max_tokens=1024
201
)
202
except BadRequestError as e:
203
print(f"Bad Request: {e.message}")
204
print(f"Request ID: {e.request_id}")
205
# Fix the request based on error message
206
if e.body:
207
print(f"Details: {e.body}")
208
```
209
210
### AuthenticationError (401)
211
212
```python { .api }
213
class AuthenticationError(APIStatusError):
214
"""
215
401 Unauthorized error.
216
217
Raised when authentication fails due to invalid or missing API key.
218
"""
219
220
status_code: Literal[401] = 401
221
```
222
223
**Common Causes:**
224
225
- Invalid API key
226
- Missing API key
227
- Expired API key
228
- API key without proper permissions
229
230
**Example:**
231
232
```python
233
import anthropic
234
from anthropic import AuthenticationError
235
236
try:
237
client = anthropic.Anthropic(api_key="invalid-key")
238
message = client.messages.create(
239
model="claude-3-5-sonnet-20241022",
240
max_tokens=1024,
241
messages=[{"role": "user", "content": "Hello!"}]
242
)
243
except AuthenticationError as e:
244
print(f"Authentication failed: {e.message}")
245
print(f"Request ID: {e.request_id}")
246
print("Please check your API key")
247
# Prompt user to enter valid API key
248
```
249
250
### PermissionDeniedError (403)
251
252
```python { .api }
253
class PermissionDeniedError(APIStatusError):
254
"""
255
403 Forbidden error.
256
257
Raised when the API key doesn't have permission for the requested resource.
258
"""
259
260
status_code: Literal[403] = 403
261
```
262
263
**Common Causes:**
264
265
- Accessing resources not available to your account
266
- Using features not included in your plan
267
- Attempting operations without proper permissions
268
269
**Example:**
270
271
```python
272
import anthropic
273
from anthropic import PermissionDeniedError
274
275
client = anthropic.Anthropic(api_key="your-api-key")
276
277
try:
278
# Attempting to use a beta feature without access
279
message = client.beta.messages.create(
280
model="claude-3-5-sonnet-20241022",
281
max_tokens=1024,
282
messages=[{"role": "user", "content": "Hello!"}],
283
betas=["restricted-beta-feature"]
284
)
285
except PermissionDeniedError as e:
286
print(f"Permission denied: {e.message}")
287
print(f"Request ID: {e.request_id}")
288
print("This feature may not be available for your account")
289
```
290
291
### NotFoundError (404)
292
293
```python { .api }
294
class NotFoundError(APIStatusError):
295
"""
296
404 Not Found error.
297
298
Raised when the requested resource doesn't exist.
299
"""
300
301
status_code: Literal[404] = 404
302
```
303
304
**Common Causes:**
305
306
- Invalid model ID
307
- Non-existent resource ID
308
- Incorrect endpoint URL
309
310
**Example:**
311
312
```python
313
import anthropic
314
from anthropic import NotFoundError
315
316
client = anthropic.Anthropic(api_key="your-api-key")
317
318
try:
319
# Using invalid model ID
320
message = client.messages.create(
321
model="non-existent-model",
322
max_tokens=1024,
323
messages=[{"role": "user", "content": "Hello!"}]
324
)
325
except NotFoundError as e:
326
print(f"Resource not found: {e.message}")
327
print(f"Request ID: {e.request_id}")
328
329
# Try with a valid model
330
message = client.messages.create(
331
model="claude-3-5-sonnet-20241022",
332
max_tokens=1024,
333
messages=[{"role": "user", "content": "Hello!"}]
334
)
335
```
336
337
### ConflictError (409)
338
339
```python { .api }
340
class ConflictError(APIStatusError):
341
"""
342
409 Conflict error.
343
344
Raised when the request conflicts with the current state of the resource.
345
"""
346
347
status_code: Literal[409] = 409
348
```
349
350
**Common Causes:**
351
352
- Attempting to create a resource that already exists
353
- Resource state conflicts with the operation
354
355
**Example:**
356
357
```python
358
import anthropic
359
from anthropic import ConflictError
360
361
client = anthropic.Anthropic(api_key="your-api-key")
362
363
try:
364
# Attempting operation that conflicts with resource state
365
result = client.beta.messages.batches.delete("batch-id")
366
except ConflictError as e:
367
print(f"Conflict: {e.message}")
368
print(f"Request ID: {e.request_id}")
369
print("The resource may be in a state that prevents this operation")
370
```
371
372
### RequestTooLargeError (413)
373
374
```python { .api }
375
class RequestTooLargeError(APIStatusError):
376
"""
377
413 Request Too Large error.
378
379
Raised when the request payload exceeds size limits.
380
"""
381
382
status_code: Literal[413] = 413
383
```
384
385
**Common Causes:**
386
387
- Request body too large
388
- Too many tokens in input
389
- Large file uploads
390
391
**Example:**
392
393
```python
394
import anthropic
395
from anthropic import RequestTooLargeError
396
397
client = anthropic.Anthropic(api_key="your-api-key")
398
399
try:
400
# Sending extremely large prompt
401
huge_content = "A" * 1000000 # Very large content
402
message = client.messages.create(
403
model="claude-3-5-sonnet-20241022",
404
max_tokens=1024,
405
messages=[{"role": "user", "content": huge_content}]
406
)
407
except RequestTooLargeError as e:
408
print(f"Request too large: {e.message}")
409
print(f"Request ID: {e.request_id}")
410
print("Please reduce the size of your request")
411
```
412
413
### UnprocessableEntityError (422)
414
415
```python { .api }
416
class UnprocessableEntityError(APIStatusError):
417
"""
418
422 Unprocessable Entity error.
419
420
Raised when the request is well-formed but contains semantic errors.
421
"""
422
423
status_code: Literal[422] = 422
424
```
425
426
**Common Causes:**
427
428
- Valid JSON but semantically invalid parameters
429
- Parameter values that violate business rules
430
- Incompatible parameter combinations
431
432
**Example:**
433
434
```python
435
import anthropic
436
from anthropic import UnprocessableEntityError
437
438
client = anthropic.Anthropic(api_key="your-api-key")
439
440
try:
441
# Invalid parameter combination
442
message = client.messages.create(
443
model="claude-3-5-sonnet-20241022",
444
max_tokens=0, # Invalid value
445
messages=[{"role": "user", "content": "Hello!"}]
446
)
447
except UnprocessableEntityError as e:
448
print(f"Unprocessable entity: {e.message}")
449
print(f"Request ID: {e.request_id}")
450
if e.body:
451
print(f"Validation errors: {e.body}")
452
```
453
454
### RateLimitError (429)
455
456
```python { .api }
457
class RateLimitError(APIStatusError):
458
"""
459
429 Rate Limit Exceeded error.
460
461
Raised when too many requests are made in a short time period.
462
"""
463
464
status_code: Literal[429] = 429
465
```
466
467
**Common Causes:**
468
469
- Exceeding requests per minute limit
470
- Exceeding tokens per minute limit
471
- Too many concurrent requests
472
473
**Example with Retry Logic:**
474
475
```python
476
import anthropic
477
from anthropic import RateLimitError
478
import time
479
480
client = anthropic.Anthropic(api_key="your-api-key")
481
482
def create_message_with_retry(max_retries=3):
483
"""Create message with exponential backoff on rate limits"""
484
for attempt in range(max_retries):
485
try:
486
message = client.messages.create(
487
model="claude-3-5-sonnet-20241022",
488
max_tokens=1024,
489
messages=[{"role": "user", "content": "Hello!"}]
490
)
491
return message
492
493
except RateLimitError as e:
494
if attempt < max_retries - 1:
495
# Exponential backoff: 1s, 2s, 4s
496
wait_time = 2 ** attempt
497
print(f"Rate limited. Retrying in {wait_time}s...")
498
print(f"Request ID: {e.request_id}")
499
500
# Check for Retry-After header
501
retry_after = e.response.headers.get("retry-after")
502
if retry_after:
503
wait_time = int(retry_after)
504
505
time.sleep(wait_time)
506
else:
507
print("Max retries reached")
508
raise
509
510
# Usage
511
try:
512
message = create_message_with_retry()
513
print(message.content[0].text)
514
except RateLimitError as e:
515
print(f"Still rate limited after retries: {e.message}")
516
```
517
518
### ServiceUnavailableError (503)
519
520
```python { .api }
521
class ServiceUnavailableError(APIStatusError):
522
"""
523
503 Service Unavailable error.
524
525
Raised when the API service is temporarily unavailable.
526
"""
527
528
status_code: Literal[503] = 503
529
```
530
531
**Common Causes:**
532
533
- Temporary service outage
534
- Maintenance
535
- Service degradation
536
537
**Example:**
538
539
```python
540
import anthropic
541
from anthropic import ServiceUnavailableError
542
import time
543
544
client = anthropic.Anthropic(api_key="your-api-key")
545
546
try:
547
message = client.messages.create(
548
model="claude-3-5-sonnet-20241022",
549
max_tokens=1024,
550
messages=[{"role": "user", "content": "Hello!"}]
551
)
552
except ServiceUnavailableError as e:
553
print(f"Service unavailable: {e.message}")
554
print(f"Request ID: {e.request_id}")
555
print("Please try again later")
556
557
# Retry after a delay
558
time.sleep(10)
559
message = client.messages.create(
560
model="claude-3-5-sonnet-20241022",
561
max_tokens=1024,
562
messages=[{"role": "user", "content": "Hello!"}]
563
)
564
```
565
566
### DeadlineExceededError (504)
567
568
```python { .api }
569
class DeadlineExceededError(APIStatusError):
570
"""
571
504 Gateway Timeout error.
572
573
Raised when the request times out on the server side.
574
"""
575
576
status_code: Literal[504] = 504
577
```
578
579
**Common Causes:**
580
581
- Server-side timeout processing request
582
- Complex operations taking too long
583
- Network issues between services
584
585
**Example:**
586
587
```python
588
import anthropic
589
from anthropic import DeadlineExceededError
590
591
client = anthropic.Anthropic(api_key="your-api-key")
592
593
try:
594
message = client.messages.create(
595
model="claude-3-5-sonnet-20241022",
596
max_tokens=4096, # Large response
597
messages=[{"role": "user", "content": "Write a very long story..."}]
598
)
599
except DeadlineExceededError as e:
600
print(f"Request timed out: {e.message}")
601
print(f"Request ID: {e.request_id}")
602
print("Try reducing max_tokens or simplifying the request")
603
```
604
605
### OverloadedError (529)
606
607
```python { .api }
608
class OverloadedError(APIStatusError):
609
"""
610
529 Overloaded error.
611
612
Raised when Anthropic's API is temporarily overloaded.
613
"""
614
615
status_code: Literal[529] = 529
616
```
617
618
**Common Causes:**
619
620
- High system load
621
- Temporary capacity constraints
622
623
**Example:**
624
625
```python
626
import anthropic
627
from anthropic import OverloadedError
628
import time
629
630
client = anthropic.Anthropic(api_key="your-api-key")
631
632
def create_with_overload_retry(max_retries=5):
633
"""Retry with exponential backoff on overload errors"""
634
for attempt in range(max_retries):
635
try:
636
message = client.messages.create(
637
model="claude-3-5-sonnet-20241022",
638
max_tokens=1024,
639
messages=[{"role": "user", "content": "Hello!"}]
640
)
641
return message
642
643
except OverloadedError as e:
644
if attempt < max_retries - 1:
645
wait_time = min(2 ** attempt, 60) # Cap at 60 seconds
646
print(f"API overloaded. Retrying in {wait_time}s...")
647
print(f"Request ID: {e.request_id}")
648
time.sleep(wait_time)
649
else:
650
raise
651
652
try:
653
message = create_with_overload_retry()
654
print(message.content[0].text)
655
except OverloadedError as e:
656
print(f"API still overloaded: {e.message}")
657
```
658
659
### InternalServerError (5xx)
660
661
```python { .api }
662
class InternalServerError(APIStatusError):
663
"""
664
Generic 5xx server error.
665
666
Raised for other 5xx status codes not covered by specific exceptions.
667
"""
668
```
669
670
**Common Causes:**
671
672
- Unexpected server errors
673
- Internal service failures
674
675
**Example:**
676
677
```python
678
import anthropic
679
from anthropic import InternalServerError
680
681
client = anthropic.Anthropic(api_key="your-api-key")
682
683
try:
684
message = client.messages.create(
685
model="claude-3-5-sonnet-20241022",
686
max_tokens=1024,
687
messages=[{"role": "user", "content": "Hello!"}]
688
)
689
except InternalServerError as e:
690
print(f"Server error: {e.message}")
691
print(f"Status code: {e.status_code}")
692
print(f"Request ID: {e.request_id}")
693
print("Please contact support if this persists")
694
```
695
696
## Connection Errors
697
698
### APIConnectionError
699
700
```python { .api }
701
class APIConnectionError(APIError):
702
"""
703
Connection error.
704
705
Raised when unable to establish a connection to the API.
706
"""
707
708
def __init__(
709
self,
710
*,
711
message: str = "Connection error.",
712
request: httpx.Request
713
) -> None: ...
714
```
715
716
**Common Causes:**
717
718
- Network connectivity issues
719
- DNS resolution failures
720
- Firewall blocking requests
721
- Invalid base URL
722
723
**Example:**
724
725
```python
726
import anthropic
727
from anthropic import APIConnectionError
728
729
try:
730
# Using invalid base URL
731
client = anthropic.Anthropic(
732
api_key="your-api-key",
733
base_url="https://invalid-url.example.com"
734
)
735
message = client.messages.create(
736
model="claude-3-5-sonnet-20241022",
737
max_tokens=1024,
738
messages=[{"role": "user", "content": "Hello!"}]
739
)
740
except APIConnectionError as e:
741
print(f"Connection failed: {e.message}")
742
print(f"Request URL: {e.request.url}")
743
print("Check your network connection and API endpoint")
744
```
745
746
### APITimeoutError
747
748
```python { .api }
749
class APITimeoutError(APIConnectionError):
750
"""
751
Request timeout error.
752
753
Raised when a request times out or is interrupted.
754
"""
755
756
def __init__(self, request: httpx.Request) -> None: ...
757
```
758
759
**Common Causes:**
760
761
- Request exceeding timeout limit
762
- Slow network connection
763
- Long-running operations
764
- Request cancellation
765
766
**Example:**
767
768
```python
769
import anthropic
770
from anthropic import APITimeoutError
771
import httpx
772
773
try:
774
# Set shorter timeout
775
client = anthropic.Anthropic(
776
api_key="your-api-key",
777
timeout=httpx.Timeout(10.0, connect=5.0) # 10s total, 5s connect
778
)
779
780
message = client.messages.create(
781
model="claude-3-5-sonnet-20241022",
782
max_tokens=4096,
783
messages=[{"role": "user", "content": "Write a very long essay..."}]
784
)
785
786
except APITimeoutError as e:
787
print(f"Request timed out: {e.message}")
788
print(f"Request URL: {e.request.url}")
789
print("Try increasing the timeout or reducing the request complexity")
790
791
# Retry with longer timeout
792
client = anthropic.Anthropic(
793
api_key="your-api-key",
794
timeout=httpx.Timeout(60.0, connect=10.0)
795
)
796
797
message = client.messages.create(
798
model="claude-3-5-sonnet-20241022",
799
max_tokens=4096,
800
messages=[{"role": "user", "content": "Write a very long essay..."}]
801
)
802
```
803
804
## Validation Errors
805
806
### APIResponseValidationError
807
808
```python { .api }
809
class APIResponseValidationError(APIError):
810
"""
811
Response validation error.
812
813
Raised when the API response doesn't match the expected schema.
814
"""
815
816
response: httpx.Response
817
"""The HTTP response object"""
818
819
status_code: int
820
"""HTTP status code"""
821
822
def __init__(
823
self,
824
response: httpx.Response,
825
body: object | None,
826
*,
827
message: str | None = None
828
) -> None: ...
829
```
830
831
**Common Causes:**
832
833
- API returning unexpected data format
834
- Schema mismatch between SDK and API versions
835
- Corrupted response data
836
837
**Example:**
838
839
```python
840
import anthropic
841
from anthropic import APIResponseValidationError
842
843
client = anthropic.Anthropic(api_key="your-api-key")
844
845
try:
846
message = client.messages.create(
847
model="claude-3-5-sonnet-20241022",
848
max_tokens=1024,
849
messages=[{"role": "user", "content": "Hello!"}]
850
)
851
except APIResponseValidationError as e:
852
print(f"Invalid response: {e.message}")
853
print(f"Status code: {e.status_code}")
854
print(f"Response body: {e.body}")
855
print("The API may have returned unexpected data")
856
print("Please ensure you're using the latest SDK version")
857
```
858
859
## Best Practices
860
861
### Comprehensive Error Handling
862
863
Handle different error types appropriately:
864
865
```python
866
import anthropic
867
from anthropic import (
868
AuthenticationError,
869
RateLimitError,
870
BadRequestError,
871
APIConnectionError,
872
APITimeoutError,
873
InternalServerError,
874
AnthropicError
875
)
876
import time
877
878
def create_message_robust(client, model, messages, max_tokens=1024):
879
"""Create message with comprehensive error handling"""
880
max_retries = 3
881
retry_count = 0
882
883
while retry_count < max_retries:
884
try:
885
return client.messages.create(
886
model=model,
887
max_tokens=max_tokens,
888
messages=messages
889
)
890
891
except AuthenticationError as e:
892
# Don't retry auth errors
893
print(f"Authentication failed: {e.message}")
894
print("Please check your API key")
895
raise
896
897
except BadRequestError as e:
898
# Don't retry bad requests
899
print(f"Bad request: {e.message}")
900
print(f"Request ID: {e.request_id}")
901
if e.body:
902
print(f"Details: {e.body}")
903
raise
904
905
except RateLimitError as e:
906
# Retry with exponential backoff
907
retry_count += 1
908
if retry_count >= max_retries:
909
raise
910
911
wait_time = 2 ** retry_count
912
retry_after = e.response.headers.get("retry-after")
913
if retry_after:
914
wait_time = int(retry_after)
915
916
print(f"Rate limited. Waiting {wait_time}s... (attempt {retry_count})")
917
time.sleep(wait_time)
918
919
except (APIConnectionError, APITimeoutError) as e:
920
# Retry connection/timeout errors
921
retry_count += 1
922
if retry_count >= max_retries:
923
raise
924
925
print(f"Connection issue. Retrying... (attempt {retry_count})")
926
time.sleep(2)
927
928
except InternalServerError as e:
929
# Retry server errors
930
retry_count += 1
931
if retry_count >= max_retries:
932
raise
933
934
print(f"Server error. Retrying... (attempt {retry_count})")
935
print(f"Request ID: {e.request_id}")
936
time.sleep(5)
937
938
except AnthropicError as e:
939
# Catch any other SDK errors
940
print(f"Unexpected error: {e}")
941
raise
942
943
# Usage
944
client = anthropic.Anthropic(api_key="your-api-key")
945
946
try:
947
message = create_message_robust(
948
client,
949
model="claude-3-5-sonnet-20241022",
950
messages=[{"role": "user", "content": "Hello!"}]
951
)
952
print(message.content[0].text)
953
954
except AnthropicError as e:
955
print(f"Failed after retries: {e}")
956
```
957
958
### Async Error Handling
959
960
Error handling in async contexts:
961
962
```python
963
import anthropic
964
from anthropic import RateLimitError, AnthropicError
965
import asyncio
966
967
async def create_message_async_robust(client, model, messages):
968
"""Async message creation with error handling"""
969
max_retries = 3
970
971
for attempt in range(max_retries):
972
try:
973
return await client.messages.create(
974
model=model,
975
max_tokens=1024,
976
messages=messages
977
)
978
979
except RateLimitError as e:
980
if attempt < max_retries - 1:
981
wait_time = 2 ** attempt
982
print(f"Rate limited. Waiting {wait_time}s...")
983
await asyncio.sleep(wait_time)
984
else:
985
raise
986
987
except AnthropicError as e:
988
print(f"Error: {e}")
989
raise
990
991
# Usage
992
async def main():
993
client = anthropic.AsyncAnthropic(api_key="your-api-key")
994
995
try:
996
message = await create_message_async_robust(
997
client,
998
model="claude-3-5-sonnet-20241022",
999
messages=[{"role": "user", "content": "Hello!"}]
1000
)
1001
print(message.content[0].text)
1002
1003
except AnthropicError as e:
1004
print(f"Failed: {e}")
1005
1006
finally:
1007
await client.close()
1008
1009
asyncio.run(main())
1010
```
1011
1012
### Logging and Monitoring
1013
1014
Log errors with context for debugging:
1015
1016
```python
1017
import anthropic
1018
from anthropic import APIStatusError, AnthropicError
1019
import logging
1020
1021
# Configure logging
1022
logging.basicConfig(
1023
level=logging.INFO,
1024
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
1025
)
1026
logger = logging.getLogger(__name__)
1027
1028
def create_message_with_logging(client, model, messages):
1029
"""Create message with detailed error logging"""
1030
try:
1031
logger.info(f"Creating message with model: {model}")
1032
1033
message = client.messages.create(
1034
model=model,
1035
max_tokens=1024,
1036
messages=messages
1037
)
1038
1039
logger.info(f"Message created successfully. ID: {message.id}")
1040
return message
1041
1042
except APIStatusError as e:
1043
# Log status errors with full context
1044
logger.error(
1045
f"API Status Error: {e.status_code}",
1046
extra={
1047
"status_code": e.status_code,
1048
"request_id": e.request_id,
1049
"message": e.message,
1050
"url": str(e.request.url),
1051
"body": e.body
1052
}
1053
)
1054
raise
1055
1056
except AnthropicError as e:
1057
# Log other SDK errors
1058
logger.error(f"Anthropic Error: {e}")
1059
raise
1060
1061
except Exception as e:
1062
# Log unexpected errors
1063
logger.exception(f"Unexpected error: {e}")
1064
raise
1065
1066
# Usage
1067
client = anthropic.Anthropic(api_key="your-api-key")
1068
1069
try:
1070
message = create_message_with_logging(
1071
client,
1072
model="claude-3-5-sonnet-20241022",
1073
messages=[{"role": "user", "content": "Hello!"}]
1074
)
1075
except AnthropicError:
1076
logger.error("Message creation failed")
1077
```
1078
1079
### Circuit Breaker Pattern
1080
1081
Implement circuit breaker to prevent cascading failures:
1082
1083
```python
1084
import anthropic
1085
from anthropic import AnthropicError, APIStatusError
1086
import time
1087
from enum import Enum
1088
1089
class CircuitState(Enum):
1090
CLOSED = "closed" # Normal operation
1091
OPEN = "open" # Blocking requests
1092
HALF_OPEN = "half_open" # Testing if service recovered
1093
1094
class CircuitBreaker:
1095
def __init__(self, failure_threshold=5, timeout=60):
1096
self.failure_threshold = failure_threshold
1097
self.timeout = timeout
1098
self.failures = 0
1099
self.last_failure_time = None
1100
self.state = CircuitState.CLOSED
1101
1102
def call(self, func, *args, **kwargs):
1103
"""Execute function with circuit breaker protection"""
1104
if self.state == CircuitState.OPEN:
1105
if time.time() - self.last_failure_time > self.timeout:
1106
self.state = CircuitState.HALF_OPEN
1107
else:
1108
raise Exception("Circuit breaker is OPEN")
1109
1110
try:
1111
result = func(*args, **kwargs)
1112
1113
# Success - reset failures
1114
if self.state == CircuitState.HALF_OPEN:
1115
self.state = CircuitState.CLOSED
1116
self.failures = 0
1117
1118
return result
1119
1120
except (APIStatusError, AnthropicError) as e:
1121
self.failures += 1
1122
self.last_failure_time = time.time()
1123
1124
if self.failures >= self.failure_threshold:
1125
self.state = CircuitState.OPEN
1126
1127
raise
1128
1129
# Usage
1130
client = anthropic.Anthropic(api_key="your-api-key")
1131
circuit_breaker = CircuitBreaker(failure_threshold=3, timeout=30)
1132
1133
def create_message():
1134
return client.messages.create(
1135
model="claude-3-5-sonnet-20241022",
1136
max_tokens=1024,
1137
messages=[{"role": "user", "content": "Hello!"}]
1138
)
1139
1140
try:
1141
message = circuit_breaker.call(create_message)
1142
print(message.content[0].text)
1143
except Exception as e:
1144
print(f"Error: {e}")
1145
```
1146
1147
### Graceful Degradation
1148
1149
Implement fallback strategies when errors occur:
1150
1151
```python
1152
import anthropic
1153
from anthropic import AnthropicError, RateLimitError, InternalServerError
1154
1155
class MessageService:
1156
def __init__(self, api_key, fallback_model=None):
1157
self.client = anthropic.Anthropic(api_key=api_key)
1158
self.primary_model = "claude-3-5-sonnet-20241022"
1159
self.fallback_model = fallback_model or "claude-3-haiku-20240307"
1160
1161
def create_message(self, messages, max_tokens=1024, allow_fallback=True):
1162
"""Create message with automatic fallback to different model"""
1163
# Try primary model
1164
try:
1165
return self.client.messages.create(
1166
model=self.primary_model,
1167
max_tokens=max_tokens,
1168
messages=messages
1169
)
1170
1171
except RateLimitError as e:
1172
if not allow_fallback:
1173
raise
1174
1175
print(f"Primary model rate limited. Trying fallback model...")
1176
# Try fallback model
1177
try:
1178
return self.client.messages.create(
1179
model=self.fallback_model,
1180
max_tokens=max_tokens,
1181
messages=messages
1182
)
1183
except AnthropicError:
1184
# If fallback also fails, raise original error
1185
raise e
1186
1187
except InternalServerError as e:
1188
if not allow_fallback:
1189
raise
1190
1191
print(f"Primary model error. Trying fallback model...")
1192
try:
1193
return self.client.messages.create(
1194
model=self.fallback_model,
1195
max_tokens=max_tokens,
1196
messages=messages
1197
)
1198
except AnthropicError:
1199
raise e
1200
1201
# Usage
1202
service = MessageService(api_key="your-api-key")
1203
1204
try:
1205
message = service.create_message(
1206
messages=[{"role": "user", "content": "Hello!"}]
1207
)
1208
print(message.content[0].text)
1209
except AnthropicError as e:
1210
print(f"All attempts failed: {e}")
1211
```
1212
1213
## Retry Strategies
1214
1215
### Exponential Backoff with Jitter
1216
1217
Implement exponential backoff with jitter to avoid thundering herd:
1218
1219
```python
1220
import anthropic
1221
from anthropic import RateLimitError, InternalServerError
1222
import time
1223
import random
1224
1225
def create_message_with_backoff(
1226
client,
1227
model,
1228
messages,
1229
max_retries=5,
1230
base_delay=1,
1231
max_delay=60
1232
):
1233
"""Create message with exponential backoff and jitter"""
1234
for attempt in range(max_retries):
1235
try:
1236
return client.messages.create(
1237
model=model,
1238
max_tokens=1024,
1239
messages=messages
1240
)
1241
1242
except (RateLimitError, InternalServerError) as e:
1243
if attempt == max_retries - 1:
1244
raise
1245
1246
# Calculate exponential backoff with jitter
1247
exponential_delay = min(base_delay * (2 ** attempt), max_delay)
1248
jitter = random.uniform(0, exponential_delay * 0.1)
1249
delay = exponential_delay + jitter
1250
1251
print(f"Attempt {attempt + 1} failed. Retrying in {delay:.2f}s...")
1252
print(f"Error: {e.message}")
1253
if hasattr(e, 'request_id'):
1254
print(f"Request ID: {e.request_id}")
1255
1256
time.sleep(delay)
1257
1258
# Usage
1259
client = anthropic.Anthropic(api_key="your-api-key")
1260
1261
message = create_message_with_backoff(
1262
client,
1263
model="claude-3-5-sonnet-20241022",
1264
messages=[{"role": "user", "content": "Hello!"}]
1265
)
1266
print(message.content[0].text)
1267
```
1268
1269
## Common Imports
1270
1271
```python
1272
from anthropic import (
1273
# Base exceptions
1274
AnthropicError,
1275
APIError,
1276
APIStatusError,
1277
1278
# HTTP status errors
1279
BadRequestError,
1280
AuthenticationError,
1281
PermissionDeniedError,
1282
NotFoundError,
1283
ConflictError,
1284
RequestTooLargeError,
1285
UnprocessableEntityError,
1286
RateLimitError,
1287
ServiceUnavailableError,
1288
DeadlineExceededError,
1289
OverloadedError,
1290
InternalServerError,
1291
1292
# Connection errors
1293
APIConnectionError,
1294
APITimeoutError,
1295
1296
# Validation errors
1297
APIResponseValidationError,
1298
)
1299
```
1300