Agent SDK troubleshooting
Fix Agent SDK errors when the Claude Code binary will not start, the process exits unexpectedly, or a successful run has no structured output.
Most Agent SDK failures fall into three buckets: the SDK cannot find or launch the Claude Code binary, the binary starts but exits partway through, or the run finishes "successfully" without the data you asked for. This page is organised by the error text you actually see, so search for your message and jump straight to the fix.
Where to look for other symptoms
Feature-specific problems are covered on the page for that feature.
| What you are seeing | Where to look |
|---|---|
Skill not found or not used, Invalid skill name | SDK skills |
MCP server status failed, tools never called or missing, connection timeouts, tool output over the token limit | MCP in the SDK |
| Plugin not loading, plugin skills missing | SDK plugins |
| Claude not delegating, filesystem agents not loading | SDK subagents |
No file checkpoint found, File rewinding is not enabled, ProcessTransport is not ready for writing, user messages without UUIDs | File checkpointing |
Hook not firing, matcher not matching, hook timeouts, modified input ignored, recursive hook loops with subagents, systemMessage missing | SDK hooks |
| Works locally, fails in a container or hosted service | Hosting the SDK |
Not logged in, Invalid API key, API Error, 429, model selection errors | Errors reference |
Everything else (CLINotFoundError, CLIConnectionError, ProcessError, ResultError, process exit codes and missing structured_output) is covered below.
The binary cannot be found
Python: CLINotFoundError
The Python SDK runs Claude Code as a child process. If it cannot locate a claude executable you get:
Claude Code not found at: /opt/tools/claude
The path appears when you set ClaudeAgentOptions(cli_path=...) and it points nowhere. Without cli_path, the SDK searches PATH plus the usual install locations, and the error includes platform-specific install instructions.
Work through these:
- Is Claude Code installed at all? See setup for native install commands.
- If you set
cli_path, does that file exist and is it theclaudeexecutable? - If you rely on
PATH, runclaude --versionfrom the same environment your app runs in. A process started by an IDE, launchd, systemd or a task scheduler often gets a much shorterPATHthan your interactive shell.
TypeScript: native binary not found
The TypeScript SDK looks in its bundled platform package, then at pathToClaudeCodeExecutable if set.
| Message | Cause | Fix |
|---|---|---|
Native CLI binary for <platform>-<arch> not found | The platform package was not installed, usually because optional dependencies were skipped (npm ci --omit=optional) | Reinstall without skipping optional dependencies, or install Claude Code natively and set pathToClaudeCodeExecutable |
Claude Code native binary not found at <path> | The resolved file is missing or unreadable | Check the path and the process's file permissions |
Claude Code executable not found at <path>. Is options.pathToClaudeCodeExecutable set? | Same as above, for a configured path | Correct or remove the option |
If you see the first message inside a single-file executable built with bun build --compile, the cause is different: the binary has to be shipped alongside the compiled app. The TypeScript reference covers compiling to a single executable.
The binary is found but will not start
Windows: Refusing to execute batch script
On Windows, the Python SDK refuses to launch a .bat or .cmd file, including the claude.cmd shim that an npm global install creates. The error names the file and suggests alternatives.
This is intentional. Windows runs batch files through cmd.exe, which re-parses the whole command line, so an argument containing the right characters could run arbitrary commands. There is no reliable way to escape for cmd.exe, so the SDK will not try.
You will only hit this if:
- you pointed
cli_pathat a batch file, or - there is no bundled or native
claude.exeavailable (for example a source install on ARM64 Windows where the npm shim is the onlyclaudeonPATH).
To fix it, give the SDK a real executable:
- Remove
cli_path, or point it at aclaude.exe. Whilecli_pathis set the SDK does no discovery of its own, so installing natively is not enough on its own. - Install Claude Code natively from PowerShell:
irm https://claude.ai/install.ps1 | iex - On x64 Windows, make sure you have the platform wheel of
claude-agent-sdk, which bundlesclaude.exe.
The SDK prefers its bundled binary, then any native claude.exe it finds, and only then a batch shim. Versions before 0.2.124 ran batch files through cmd.exe without this check.
Failed to start or failed to launch
Here a file exists at the resolved path but the operating system cannot run it.
| Message | SDK | Meaning |
|---|---|---|
Failed to start Claude Code: <detail> | Python (CLIConnectionError) | The detail is the OS error |
Claude Code executable at <path> exists but failed to launch | TypeScript | The configured script cannot run |
Claude Code native binary at <path> exists but failed to launch | TypeScript | The binary cannot run; a libc hint is appended |
Failed to spawn Claude Code process: <detail> | TypeScript | Any other spawn failure |
TypeScript surfaces these as an ordinary rejected iteration, not a named SDK error class.
The usual culprit is a path pointing at the wrong kind of thing: a text file, a directory, or a binary without the execute bit. Treat the libc hint as one possibility, not a diagnosis. To fix:
- Make sure the path is the
claudeexecutable itself and is executable (chmod +x). - Drop
cli_pathorpathToClaudeCodeExecutableif you do not need it; the SDK will use its bundled copy. - In containers, reinstall the SDK during the image build so the bundled binary matches the image's architecture and libc (an Alpine musl image needs a different binary from a Debian glibc one), and check the execute permission survived any
COPYsteps. Building on an Apple Silicon laptop for an x64 server is a classic way to end up with the wrong one.
Python: Not connected. Call connect() first.
You called a ClaudeSDKClient method before connecting or after disconnecting. Either await client.connect() first, or use the context manager, which connects on entry:
async with ClaudeSDKClient(options=opts) as client:
await client.query("Check the staging logs for 500s")
async for msg in client.receive_response():
...
The process exits partway through
These errors mean the Claude Code process ended while your app was still talking to it. What you see depends on the language and on whether the CLI managed to report an error before exiting.
Python: ProcessError
Command failed with exit code 1 (exit code: 1)
Error output: Check stderr output for details
Do not be misled by the second line: it is fixed placeholder text, not the real stderr, and the exception's stderr attribute holds the same placeholder. exit_code holds the code. To see what the CLI actually printed, pass a stderr callback in ClaudeAgentOptions and log every line it receives.
A plain ProcessError means the CLI died without reporting an error result. If it did report one, you get a ResultError instead (next section). ResultError is a subclass of ProcessError, so order your handlers with the specific one first:
from claude_agent_sdk import ProcessError, ResultError
try:
async for msg in query(prompt=task, options=opts):
handle(msg)
except ResultError as err:
log.error("CLI reported failure: %s", err.data)
except ProcessError as err:
log.error("CLI exited with %s", err.exit_code)
Before 0.2.140, error-result exits were raised as a plain Exception.
TypeScript: Claude Code process exited with code N
The TypeScript SDK rejects the for await loop with a plain Error. There is no class to match, so catch and inspect the message:
Claude Code process exited with code 1. stderr: <last part of stderr>
The tail of stderr is appended when there was any. For the full stream, pass a stderr callback in the options. If a signal killed the process, the message reads Claude Code process terminated by signal <name> instead. IDE integrations show this same message; the errors reference covers those launchers.
Claude Code returned an error result
When the CLI reported an error before exiting, both SDKs give you:
Claude Code returned an error result: <the CLI's report>
Read the text after the colon first: it is Claude Code's own account of what went wrong, and usually more useful than the exit code. Python raises ResultError with the full result in .data; TypeScript rejects with a plain Error in the same format.
Successful run, no structured output
A result message can have subtype: "success" while structured_output is None (Python) or undefined (TypeScript). The run finished, but nothing validated against your schema. A schema that no output can satisfy, such as a string with minLength greater than its maxLength, is one way to get here.
Treat it as a failure: check both the subtype and that structured_output is present before you use it. Structured outputs shows the pattern. If it keeps happening with a schema you believe is sound, strip the schema back until outputs validate, then add constraints back one at a time.
Still stuck
Search the issue trackers, and if nothing matches, open a new issue with the full error text and your SDK version: