anthropics / anthropics/claude-agent-sdk-python

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

オープン
#798 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Python
スター
8.1k
フォーク
1.3k
平均マージ
2日 31分
マージ済み PR(30日)
1

説明

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

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。