anthropics / anthropics/claude-agent-sdk-python

Error context destroyed through exception flattening — CLI failures produce unhelpful 'Command failed with exit code 1'

Aperta
#798 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Python
Stelle
8.1k
Fork
1.3k
Merge medio
2g 31m
PR unite (30g)
1

Descrizione

### SDK version
`claude-agent-sdk==0.1.56`

### Description

When the Claude CLI subprocess exits with a non-zero code, the SDK destroys all error context through a 3-step chain, making failures impossible to diagnose:

1. **`_internal/transport/subprocess_cli.py:614`** — `ProcessError` is created with `stderr="Check stderr output for details"` (hardcoded string, not actual stderr from the process)
2. **`_internal/query.py:250`** — Caught in `_read_task`, flattened via `str(e)`, sent as `{"type": "error", "error": str(e)}` through the message stream
3. **`_internal/query.py:726`** — `receive_messages()` re-raises as bare `Exception(message.get("error"))`, losing the `ProcessError` type entirely

Consumer code that catches `ClaudeSDKError` never fires because the exception arrives as bare `Exception`.

### Reproduction

Any scenario where the Claude CLI process exits with code 1 (permission denied, internal error, bad config). The consumer receives:

```
Exception: Command failed with exit code 1 (exit code: 1)
Error output: Check stderr output for details
```

No actual stderr, no typed exception, no actionable detail.

### Issues found (in order of severity)

| File | Line | Problem |
|------|------|---------|
| `subprocess_cli.py` | 616 | `stderr="Check stderr output for details"` is **hardcoded** — actual stderr is never captured into the error |
| `query.py` | 250 | `str(e)` flattens `ProcessError` (which has `exit_code`/`stderr` attrs) into a plain string |
| `query.py` | 726 | `raise Exception(...)` instead of preserving/re-raising original exception type — `except ClaudeSDKError` in consumer code never triggers |
| `query.py` | 207-209 | Control request errors also create bare `Exception` from dict |
| `subprocess_cli.py` | 446-449 | stderr reading exceptions silently swallowed (`except Exception: pass`) |
| `subprocess_cli.py` | 608 | `process.wait()` failure caught as `returncode = -1`, no logging |
| `query.py` | 272, 318, 334, 346, 385, 420 | Bare `Exception()` instead of typed `ClaudeSDKError` subclasses |

### Expected behavior

1. `ProcessError.stderr` should contain the **actual stderr output** from the CLI process, not a hardcoded string
2. `query.py:726` should raise `ProcessError` (or at minimum `ClaudeSDKError`), not bare `Exception` — so consumer `except ClaudeSDKError` blocks work
3. `query.py:250` should preserve the exception object (or at least its type and attributes) rather than stringifying it

### Workaround

Consumer code must catch `Exception` (not `ClaudeSDKError`) and try `getattr(exc, "exit_code", None)` defensively. But even that doesn't help here because the attributes are stripped at step 2 before re-raising.

### Environment

- Python 3.14.3
- claude-agent-sdk 0.1.56
- Windows 11
- Claude Code CLI installed via npm

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.