| name | Claude SDK Debugging |
| description | Comprehensive guide for debugging Claude Agent SDK errors, TypedDict contracts, and internal SDK processing issues |
| keywords | ["claude-sdk","sdk-error","mcp","typeddict","serialization","json-error","sdk-debugging"] |
Claude SDK Debugging Guide
When to Use This
- SDK-related errors (Claude Agent SDK, MCP servers)
- JSON serialization errors involving SDK objects
- TypedDict mismatch errors
- SDK internal processing failures
- MCP server configuration errors
Debugging Strategy
1. Get Full Error Traceback
CRITICAL: User-facing errors don't show root cause. Always check log files.
tail -50 logs/errors.log
grep "JSON serializable" logs/errors.log | tail -5
tail -100 logs/errors.log | grep -A 20 "ERROR"
Why: SDK errors surface deep in internal code. Full tracebacks show:
- Exact SDK file and line number where error occurred
- Complete call stack leading to the error
- Actual vs expected data structures
2. Locate SDK Source Code
Once you have the traceback, find the SDK source file:
find .venv/lib -name "subprocess_cli.py" -path "*/claude_agent_sdk/*"
find /Users/$USER/.local/lib -name "*sdk*"
Read the SDK code at the failure point to understand:
- What the SDK expects
- How it processes the data
- What checks it performs
3. Understand SDK Internal Processing
Example: McpSdkServerConfig Serialization
Error: Object of type Server is not JSON serializable
Traceback shows: subprocess_cli.py:169 - json.dumps({"mcpServers": servers_for_cli})
Read SDK source at line 154-169:
if isinstance(config, dict) and config.get("type") == "sdk":
sdk_config = {k: v for k, v in config.items() if k != "instance"}
servers_for_cli[name] = sdk_config
else:
servers_for_cli[name] = config
json.dumps({"mcpServers": servers_for_cli})
Root cause: SDK strips instance field but only if:
config.get("type") == "sdk" (must have type key)
- Checking
k != "instance" (must use instance key, not server)
4. Common SDK Contracts
McpSdkServerConfig TypedDict
McpSdkServerConfig(
type="sdk",
name="server_name",
instance=server
)
McpSdkServerConfig(
server=server,
name="name"
)
Why it matters:
- TypedDict is just a dict at runtime - wrong keys don't error immediately
- Error surfaces later when SDK tries to process it
- SDK's internal logic depends on exact key names
ClaudeAgentOptions.mcp_servers
options = ClaudeAgentOptions(
mcp_servers={
"server_name": create_sdk_mcp_server(
name="server_name",
version="1.0.0",
tools=[tool1, tool2]
)
}
)
5. SDK Bug Fix Checklist
When patching SDK bugs:
Example: Patching create_sdk_mcp_server
def patched_create_sdk_mcp_server(
name: str,
version: str = "1.0.0",
tools: list[SdkMcpTool] | None = None,
) -> McpSdkServerConfig:
"""Patched version fixing bug #323."""
from mcp.server import Server
server = Server(name)
return McpSdkServerConfig(
type="sdk",
name=name,
instance=server
)
6. Verification Strategy
After fixing SDK bugs:
result = create_sdk_mcp_server(name="test", tools=[tool1])
assert result["type"] == "sdk"
assert result["name"] == "test"
assert "instance" in result
sdk_config = {k: v for k, v in result.items() if k != "instance"}
import json
json.dumps({"mcpServers": {"test": sdk_config}})
options = ClaudeAgentOptions(mcp_servers={"test": result})
async with ClaudeSDKClient(options=options) as client:
pass
Common Patterns
Pattern 1: TypedDict Mismatch
Symptom: Error occurs in SDK internal code, not at return statement
Cause: Wrong TypedDict keys - runtime doesn't validate, fails downstream
Solution: Read SDK source to find exact keys it expects
Pattern 2: JSON Serialization Errors
Symptom: Object of type X is not JSON serializable
Cause: SDK failed to strip non-serializable fields
Solution:
- Check if SDK has stripping logic (like
k != "instance")
- Verify your keys match SDK's strip conditions
- Ensure identification keys are present (like
type="sdk")
Pattern 3: SDK Parameter Bugs
Symptom: TypeError: __init__() got unexpected keyword argument
Cause: SDK passes parameters that underlying library doesn't accept
Solution:
- Patch to remove unsupported parameters
- But also verify SDK's processing still works
- Match SDK's expected return structure
Key Takeaways
- Always check full tracebacks - User errors hide root cause
- Read SDK source - Internal processing reveals requirements
- Match exact TypedDict keys - Runtime doesn't validate structure
- Test downstream - Fix original bug AND SDK's usage
- Document SDK source refs - Future debugging and maintenance
Quick Reference
tail -50 logs/errors.log
find .venv/lib -name "*subprocess_cli*"
python -c "from claude_agent_sdk import McpSdkServerConfig; print(McpSdkServerConfig.__required_keys__)"
Related