anthropics / anthropics/claude-agent-sdk-python

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

Offen
#798 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
Vorherrschende Sprache
Python
Sterne
8.1k
Forks
1.3k
Ø Merge
2 T. 31 Min.
Gemergte PRs (30 T.)
1

Beschreibung

### 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

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.