docs
0
# Error Types
1
2
The Claude Agent SDK defines a hierarchy of exception types for different error conditions. All SDK errors inherit from ClaudeSDKError, making it easy to catch all SDK-related exceptions.
3
4
## Capabilities
5
6
### ClaudeSDKError
7
8
Base exception for all Claude SDK errors.
9
10
```python { .api }
11
class ClaudeSDKError(Exception):
12
"""
13
Base exception for all Claude SDK errors.
14
15
All SDK-specific exceptions inherit from this class, allowing you
16
to catch all SDK errors with a single except clause.
17
18
Example:
19
try:
20
async for msg in query(prompt="Hello"):
21
print(msg)
22
except ClaudeSDKError as e:
23
print(f"SDK error: {e}")
24
"""
25
```
26
27
### CLIConnectionError
28
29
Raised when unable to connect to Claude Code.
30
31
```python { .api }
32
class CLIConnectionError(ClaudeSDKError):
33
"""
34
Raised when unable to connect to Claude Code.
35
36
This error occurs when the SDK cannot establish a connection to the
37
Claude Code CLI process. This can happen if:
38
- The CLI is not installed
39
- The CLI path is incorrect
40
- Network issues (for remote transports)
41
- Permission issues
42
43
Inherits from: ClaudeSDKError
44
"""
45
```
46
47
### CLINotFoundError
48
49
Raised when Claude Code CLI is not found or not installed.
50
51
```python { .api }
52
class CLINotFoundError(CLIConnectionError):
53
"""
54
Raised when Claude Code is not found or not installed.
55
56
This specific connection error occurs when the SDK cannot locate the
57
Claude Code CLI executable. This typically means Claude Code is not
58
installed or not in the system PATH.
59
60
Inherits from: CLIConnectionError
61
62
Constructor:
63
__init__(
64
message: str = "Claude Code not found",
65
cli_path: str | None = None
66
)
67
68
Attributes:
69
cli_path: The path where the CLI was expected (if known)
70
"""
71
72
def __init__(
73
self,
74
message: str = "Claude Code not found",
75
cli_path: str | None = None
76
):
77
"""
78
Initialize CLINotFoundError.
79
80
Args:
81
message: Error message. Defaults to "Claude Code not found"
82
cli_path: Optional path where CLI was expected. If provided,
83
will be appended to the error message.
84
85
Example:
86
CLINotFoundError("Custom message", "/usr/local/bin/claude")
87
"""
88
```
89
90
### ProcessError
91
92
Raised when the CLI process fails.
93
94
```python { .api }
95
class ProcessError(ClaudeSDKError):
96
"""
97
Raised when the CLI process fails.
98
99
This error occurs when the Claude Code CLI process exits with an error
100
or fails during execution. Contains details about the failure including
101
exit code and stderr output.
102
103
Inherits from: ClaudeSDKError
104
105
Constructor:
106
__init__(
107
message: str,
108
exit_code: int | None = None,
109
stderr: str | None = None
110
)
111
112
Attributes:
113
exit_code: Process exit code (if available)
114
stderr: Standard error output from the process (if available)
115
"""
116
117
def __init__(
118
self,
119
message: str,
120
exit_code: int | None = None,
121
stderr: str | None = None
122
):
123
"""
124
Initialize ProcessError.
125
126
Args:
127
message: Error description
128
exit_code: Optional process exit code
129
stderr: Optional stderr output from process
130
131
Example:
132
ProcessError(
133
"Process failed",
134
exit_code=1,
135
stderr="Error: Invalid argument"
136
)
137
138
Notes:
139
- Exit code and stderr are automatically appended to the message
140
- The formatted message includes exit code if available
141
- Stderr output is included in formatted message if available
142
"""
143
144
exit_code: int | None
145
"""Process exit code.
146
147
The exit code returned by the CLI process. None if process didn't
148
exit normally or exit code is unknown.
149
150
Common values:
151
- 0: Success (but wouldn't raise ProcessError)
152
- 1: General error
153
- 2: Misuse of shell command
154
- 126: Command cannot execute
155
- 127: Command not found
156
- 130: Terminated by Ctrl+C
157
"""
158
159
stderr: str | None
160
"""Standard error output.
161
162
The stderr output from the CLI process. None if no stderr was captured
163
or process didn't produce stderr output.
164
165
This typically contains error messages, warnings, and diagnostic
166
information from the CLI.
167
"""
168
```
169
170
### CLIJSONDecodeError
171
172
Raised when unable to decode JSON from CLI output.
173
174
```python { .api }
175
class CLIJSONDecodeError(ClaudeSDKError):
176
"""
177
Raised when unable to decode JSON from CLI output.
178
179
This error occurs when the CLI produces output that cannot be parsed
180
as JSON. This usually indicates a protocol error or corrupted output.
181
182
Inherits from: ClaudeSDKError
183
184
Constructor:
185
__init__(line: str, original_error: Exception)
186
187
Attributes:
188
line: The line that failed to parse
189
original_error: The underlying JSON decode exception
190
"""
191
192
def __init__(self, line: str, original_error: Exception):
193
"""
194
Initialize CLIJSONDecodeError.
195
196
Args:
197
line: The line that failed to parse (truncated to 100 chars in message)
198
original_error: The original exception from JSON parsing
199
200
Example:
201
CLIJSONDecodeError(
202
"{invalid json",
203
json.JSONDecodeError("msg", "doc", 0)
204
)
205
206
Notes:
207
- Error message shows first 100 characters of problematic line
208
- Original error is preserved for debugging
209
"""
210
211
line: str
212
"""Line that failed to parse.
213
214
The complete line from CLI output that could not be decoded as JSON.
215
This is the raw string that caused the parsing error.
216
"""
217
218
original_error: Exception
219
"""Original exception.
220
221
The underlying exception that occurred during JSON parsing. Usually
222
a json.JSONDecodeError with details about what went wrong.
223
224
Useful for debugging the specific parsing issue.
225
"""
226
```
227
228
### MessageParseError
229
230
Raised when unable to parse a message from CLI output.
231
232
```python { .api }
233
class MessageParseError(ClaudeSDKError):
234
"""
235
Raised when unable to parse a message from CLI output.
236
237
This error occurs when the CLI output is valid JSON but doesn't match
238
the expected message structure. This indicates a protocol mismatch or
239
unexpected message format.
240
241
Inherits from: ClaudeSDKError
242
243
Constructor:
244
__init__(message: str, data: dict[str, Any] | None = None)
245
246
Attributes:
247
data: The message data that failed to parse (if available)
248
"""
249
250
def __init__(self, message: str, data: dict[str, Any] | None = None):
251
"""
252
Initialize MessageParseError.
253
254
Args:
255
message: Error description
256
data: Optional message data that failed to parse
257
258
Example:
259
MessageParseError(
260
"Unknown message type",
261
{"type": "unknown", "data": {...}}
262
)
263
264
Notes:
265
- Message describes what went wrong during parsing
266
- Data contains the raw message dict for debugging
267
"""
268
269
data: dict[str, Any] | None
270
"""Message data.
271
272
The parsed JSON data that couldn't be converted to a proper message
273
object. None if data is not available.
274
275
This is the dictionary that was successfully parsed as JSON but
276
doesn't match expected message schemas.
277
"""
278
```
279
280
## Usage Examples
281
282
### Basic Error Handling
283
284
```python
285
from claude_agent_sdk import query, ClaudeSDKError
286
287
try:
288
async for msg in query(prompt="Hello Claude"):
289
print(msg)
290
except ClaudeSDKError as e:
291
print(f"SDK error occurred: {e}")
292
```
293
294
### Handling Specific Errors
295
296
```python
297
from claude_agent_sdk import (
298
query, CLINotFoundError, CLIConnectionError,
299
ProcessError, ClaudeSDKError
300
)
301
302
try:
303
async for msg in query(prompt="Hello"):
304
print(msg)
305
306
except CLINotFoundError as e:
307
print("Claude Code is not installed or not in PATH")
308
print("Please install from: https://claude.com/code")
309
310
except CLIConnectionError as e:
311
print(f"Cannot connect to Claude Code: {e}")
312
print("Make sure Claude Code is running")
313
314
except ProcessError as e:
315
print(f"CLI process failed: {e}")
316
if e.exit_code:
317
print(f"Exit code: {e.exit_code}")
318
if e.stderr:
319
print(f"Error output: {e.stderr}")
320
321
except ClaudeSDKError as e:
322
print(f"Other SDK error: {e}")
323
```
324
325
### Installation Check
326
327
```python
328
from claude_agent_sdk import query, CLINotFoundError
329
330
async def check_claude_installed():
331
"""Check if Claude Code is installed."""
332
try:
333
async for msg in query(prompt="test"):
334
# If we get here, Claude is installed
335
return True
336
except CLINotFoundError:
337
return False
338
339
if await check_claude_installed():
340
print("Claude Code is installed")
341
else:
342
print("Please install Claude Code")
343
```
344
345
### Detailed Error Information
346
347
```python
348
from claude_agent_sdk import query, ProcessError
349
350
try:
351
async for msg in query(prompt="Hello"):
352
print(msg)
353
354
except ProcessError as e:
355
print("Process Error Details:")
356
print(f" Message: {e}")
357
print(f" Exit Code: {e.exit_code}")
358
print(f" Stderr: {e.stderr}")
359
360
# Check specific exit codes
361
if e.exit_code == 127:
362
print(" Diagnosis: Command not found")
363
elif e.exit_code == 126:
364
print(" Diagnosis: Command cannot execute (permission issue?)")
365
elif e.exit_code == 130:
366
print(" Diagnosis: Process interrupted by user")
367
```
368
369
### Retry Logic
370
371
```python
372
import anyio
373
from claude_agent_sdk import query, CLIConnectionError, ClaudeSDKError
374
375
async def query_with_retry(prompt: str, max_retries: int = 3):
376
"""Query with automatic retry on connection errors."""
377
for attempt in range(max_retries):
378
try:
379
async for msg in query(prompt=prompt):
380
print(msg)
381
return # Success
382
383
except CLIConnectionError as e:
384
if attempt < max_retries - 1:
385
print(f"Connection failed (attempt {attempt + 1}/{max_retries})")
386
print("Retrying in 2 seconds...")
387
await anyio.sleep(2)
388
else:
389
print("Max retries reached")
390
raise
391
392
except ClaudeSDKError:
393
# Don't retry other errors
394
raise
395
396
await query_with_retry("Hello Claude")
397
```
398
399
### JSON Decode Error Handling
400
401
```python
402
from claude_agent_sdk import query, CLIJSONDecodeError
403
404
try:
405
async for msg in query(prompt="Hello"):
406
print(msg)
407
408
except CLIJSONDecodeError as e:
409
print("Failed to parse CLI output")
410
print(f"Problematic line: {e.line[:200]}") # Show first 200 chars
411
print(f"Original error: {e.original_error}")
412
print("This might indicate a CLI version mismatch")
413
```
414
415
### Message Parse Error Handling
416
417
```python
418
from claude_agent_sdk import query, MessageParseError
419
420
try:
421
async for msg in query(prompt="Hello"):
422
print(msg)
423
424
except MessageParseError as e:
425
print("Failed to parse message structure")
426
print(f"Error: {e}")
427
if e.data:
428
print(f"Raw data: {e.data}")
429
print("This might indicate a protocol version mismatch")
430
```
431
432
### Error Logging
433
434
```python
435
import logging
436
from claude_agent_sdk import query, ClaudeSDKError, ProcessError
437
438
logging.basicConfig(level=logging.ERROR)
439
logger = logging.getLogger(__name__)
440
441
try:
442
async for msg in query(prompt="Hello"):
443
print(msg)
444
445
except ProcessError as e:
446
logger.error(
447
"Process error",
448
extra={
449
"exit_code": e.exit_code,
450
"stderr": e.stderr,
451
"message": str(e)
452
}
453
)
454
455
except ClaudeSDKError as e:
456
logger.error(f"SDK error: {e}", exc_info=True)
457
```
458
459
### Error Recovery
460
461
```python
462
from claude_agent_sdk import (
463
query, ClaudeSDKError, CLINotFoundError,
464
ProcessError, ClaudeAgentOptions
465
)
466
467
async def robust_query(prompt: str):
468
"""Query with error recovery strategies."""
469
try:
470
async for msg in query(prompt=prompt):
471
print(msg)
472
473
except CLINotFoundError:
474
print("Installing Claude Code would fix this...")
475
# Could trigger installation process here
476
raise
477
478
except ProcessError as e:
479
if e.exit_code == 1 and e.stderr and "permission" in e.stderr.lower():
480
print("Try running with different permissions")
481
else:
482
print(f"Process failed: {e}")
483
raise
484
485
except ClaudeSDKError as e:
486
print(f"Unexpected error: {e}")
487
raise
488
489
await robust_query("Hello Claude")
490
```
491
492
### User-Friendly Error Messages
493
494
```python
495
from claude_agent_sdk import (
496
query, CLINotFoundError, CLIConnectionError,
497
ProcessError, ClaudeSDKError
498
)
499
500
async def query_with_friendly_errors(prompt: str):
501
"""Query with user-friendly error messages."""
502
try:
503
async for msg in query(prompt=prompt):
504
print(msg)
505
506
except CLINotFoundError:
507
print("\nClaude Code Not Found")
508
print("=" * 50)
509
print("Claude Code needs to be installed to use this SDK.")
510
print("\nInstallation instructions:")
511
print("1. Visit https://claude.com/code")
512
print("2. Download and install Claude Code")
513
print("3. Make sure 'claude' is in your PATH")
514
515
except CLIConnectionError as e:
516
print("\nConnection Error")
517
print("=" * 50)
518
print("Could not connect to Claude Code.")
519
print(f"\nDetails: {e}")
520
print("\nPossible solutions:")
521
print("- Check if Claude Code is running")
522
print("- Try restarting Claude Code")
523
print("- Check your network connection")
524
525
except ProcessError as e:
526
print("\nProcess Error")
527
print("=" * 50)
528
print("Claude Code process encountered an error.")
529
if e.exit_code:
530
print(f"Exit code: {e.exit_code}")
531
if e.stderr:
532
print(f"Error details: {e.stderr}")
533
534
except ClaudeSDKError as e:
535
print("\nUnexpected Error")
536
print("=" * 50)
537
print(f"An unexpected error occurred: {e}")
538
print("Please report this issue if it persists")
539
540
await query_with_friendly_errors("Hello")
541
```
542
543
### Exception Chaining
544
545
```python
546
from claude_agent_sdk import query, ClaudeSDKError
547
548
class ApplicationError(Exception):
549
"""Custom application error."""
550
pass
551
552
try:
553
async for msg in query(prompt="Hello"):
554
print(msg)
555
556
except ClaudeSDKError as e:
557
# Chain SDK error with application error
558
raise ApplicationError("Failed to query Claude") from e
559
```
560
561
### Error Metrics
562
563
```python
564
from collections import defaultdict
565
from claude_agent_sdk import (
566
query, CLINotFoundError, CLIConnectionError,
567
ProcessError, ClaudeSDKError
568
)
569
570
error_counts = defaultdict(int)
571
572
async def query_with_metrics(prompt: str):
573
"""Track error types for monitoring."""
574
try:
575
async for msg in query(prompt=prompt):
576
print(msg)
577
578
except CLINotFoundError as e:
579
error_counts["cli_not_found"] += 1
580
raise
581
582
except CLIConnectionError as e:
583
error_counts["connection_error"] += 1
584
raise
585
586
except ProcessError as e:
587
error_counts["process_error"] += 1
588
raise
589
590
except ClaudeSDKError as e:
591
error_counts["other_sdk_error"] += 1
592
raise
593
594
# Later, check metrics
595
print("Error statistics:")
596
for error_type, count in error_counts.items():
597
print(f" {error_type}: {count}")
598
```
599
600
### Conditional Error Handling
601
602
```python
603
from claude_agent_sdk import query, ProcessError, ClaudeSDKError
604
605
async def handle_errors_conditionally(prompt: str, strict: bool = False):
606
"""Handle errors differently based on mode."""
607
try:
608
async for msg in query(prompt=prompt):
609
print(msg)
610
611
except ProcessError as e:
612
if strict:
613
# In strict mode, fail immediately
614
raise
615
else:
616
# In lenient mode, log and continue
617
print(f"Warning: Process error occurred: {e}")
618
print("Continuing anyway...")
619
620
except ClaudeSDKError as e:
621
if strict:
622
raise
623
else:
624
print(f"Warning: SDK error: {e}")
625
626
# Strict mode
627
await handle_errors_conditionally("Hello", strict=True)
628
629
# Lenient mode
630
await handle_errors_conditionally("Hello", strict=False)
631
```
632
633
### Error Context Manager
634
635
```python
636
from contextlib import asynccontextmanager
637
from claude_agent_sdk import query, ClaudeSDKError
638
639
@asynccontextmanager
640
async def handle_sdk_errors():
641
"""Context manager for SDK error handling."""
642
try:
643
yield
644
except ClaudeSDKError as e:
645
print(f"SDK Error: {e}")
646
# Log to file, send to monitoring, etc.
647
raise
648
649
async def main():
650
async with handle_sdk_errors():
651
async for msg in query(prompt="Hello"):
652
print(msg)
653
654
await main()
655
```
656