Skip to content

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 seeingWhere to look
Skill not found or not used, Invalid skill nameSDK skills
MCP server status failed, tools never called or missing, connection timeouts, tool output over the token limitMCP in the SDK
Plugin not loading, plugin skills missingSDK plugins
Claude not delegating, filesystem agents not loadingSDK subagents
No file checkpoint found, File rewinding is not enabled, ProcessTransport is not ready for writing, user messages without UUIDsFile checkpointing
Hook not firing, matcher not matching, hook timeouts, modified input ignored, recursive hook loops with subagents, systemMessage missingSDK hooks
Works locally, fails in a container or hosted serviceHosting the SDK
Not logged in, Invalid API key, API Error, 429, model selection errorsErrors 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:

  1. Is Claude Code installed at all? See setup for native install commands.
  2. If you set cli_path, does that file exist and is it the claude executable?
  3. If you rely on PATH, run claude --version from the same environment your app runs in. A process started by an IDE, launchd, systemd or a task scheduler often gets a much shorter PATH than your interactive shell.

TypeScript: native binary not found

The TypeScript SDK looks in its bundled platform package, then at pathToClaudeCodeExecutable if set.

MessageCauseFix
Native CLI binary for <platform>-<arch> not foundThe 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 unreadableCheck 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 pathCorrect 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_path at a batch file, or
  • there is no bundled or native claude.exe available (for example a source install on ARM64 Windows where the npm shim is the only claude on PATH).

To fix it, give the SDK a real executable:

  • Remove cli_path, or point it at a claude.exe. While cli_path is 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 bundles claude.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.

MessageSDKMeaning
Failed to start Claude Code: <detail>Python (CLIConnectionError)The detail is the OS error
Claude Code executable at <path> exists but failed to launchTypeScriptThe configured script cannot run
Claude Code native binary at <path> exists but failed to launchTypeScriptThe binary cannot run; a libc hint is appended
Failed to spawn Claude Code process: <detail>TypeScriptAny 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 claude executable itself and is executable (chmod +x).
  • Drop cli_path or pathToClaudeCodeExecutable if 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 COPY steps. 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: