claude-sdk-debugging
Comprehensive guide for debugging Claude Agent SDK errors, TypedDict contracts, and internal SDK processing issues
When & Why to Use This Skill
This Claude skill provides a comprehensive technical framework for diagnosing and resolving complex issues within the Claude Agent SDK and Model Context Protocol (MCP) environments. It focuses on identifying root causes for JSON serialization errors, TypedDict contract mismatches, and internal SDK processing failures by leveraging deep traceback analysis and source code inspection. By following these structured debugging strategies, developers can efficiently patch SDK bugs and ensure robust integration between agents and external tools.
Use Cases
- Resolving 'Object of type X is not JSON serializable' errors by identifying missing identification keys like 'type=sdk' or incorrect instance stripping logic.
- Fixing TypedDict mismatch errors where runtime dictionaries contain incorrect keys that cause failures deep within internal SDK processing.
- Debugging MCP server configuration issues by locating SDK source code in virtual environments and verifying expected data structures.
- Patching SDK-level parameter bugs, such as unexpected keyword arguments passed to underlying libraries like the MCP Server class.
- Implementing verification workflows to test downstream behavior after applying SDK fixes to ensure full system stability.
| 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.
# Check error logs
tail -50 logs/errors.log
# Grep for specific error
grep "JSON serializable" logs/errors.log | tail -5
# Check recent errors
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 SDK files in virtual environment
find .venv/lib -name "subprocess_cli.py" -path "*/claude_agent_sdk/*"
# Or in global Python packages
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":
# For SDK servers, pass everything except the instance field
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
# Line 169: JSON serialization
json.dumps({"mcpServers": servers_for_cli})
Root cause: SDK strips instance field but only if:
config.get("type") == "sdk"(must havetypekey)- Checking
k != "instance"(must useinstancekey, notserver)
4. Common SDK Contracts
McpSdkServerConfig TypedDict
# Correct structure
McpSdkServerConfig(
type="sdk", # SDK checks: config.get("type") == "sdk"
name="server_name", # Server identifier
instance=server # SDK strips before JSON: k != "instance"
)
# Wrong - causes JSON serialization error
McpSdkServerConfig(
server=server, # Wrong key! SDK can't strip this
name="name" # Missing type="sdk"
)
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
# SDK expects dict[str, McpSdkServerConfig | McpStdioServerConfig | ...]
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:
- Fix original bug (e.g., wrong parameter)
- Match SDK contracts (correct TypedDict keys)
- Read SDK internal processing (how SDK uses the return value)
- Test downstream behavior (not just immediate return)
- Verify no new errors (check logs after fix)
- Document why (comment referencing SDK source location)
Example: Patching create_sdk_mcp_server
def patched_create_sdk_mcp_server(
name: str,
version: str = "1.0.0", # Bug: SDK passes this to Server() which doesn't accept it
tools: list[SdkMcpTool] | None = None,
) -> McpSdkServerConfig:
"""Patched version fixing bug #323."""
from mcp.server import Server
# FIX 1: Don't pass version to Server.__init__()
# Original SDK bug: Server(name, version=version)
server = Server(name) # Correct: Server only accepts name
# ... tool registration ...
# FIX 2: Return with correct TypedDict keys
# SDK subprocess_cli.py:154-159 expects these exact keys:
# - type="sdk" for identification
# - name for server name
# - instance for Server object (stripped before JSON serialization)
return McpSdkServerConfig(
type="sdk", # SDK checks config.get("type") == "sdk"
name=name, # Identifier
instance=server # SDK strips: k != "instance"
)
6. Verification Strategy
After fixing SDK bugs:
# 1. Verify immediate return
result = create_sdk_mcp_server(name="test", tools=[tool1])
assert result["type"] == "sdk"
assert result["name"] == "test"
assert "instance" in result
# 2. Verify SDK processing (simulate SDK's internal logic)
sdk_config = {k: v for k, v in result.items() if k != "instance"}
import json
json.dumps({"mcpServers": {"test": sdk_config}}) # Should not error
# 3. Test full workflow
options = ClaudeAgentOptions(mcp_servers={"test": result})
async with ClaudeSDKClient(options=options) as client:
# Should successfully connect without JSON serialization errors
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
# Find error in logs
tail -50 logs/errors.log
# Find SDK source
find .venv/lib -name "*subprocess_cli*"
# Verify TypedDict structure
python -c "from claude_agent_sdk import McpSdkServerConfig; print(McpSdkServerConfig.__required_keys__)"
Related
.quibbler/rules.md- "Check Full Error Tracebacks for SDK Failures"- SDK Bug #323: https://github.com/anthropics/claude-agent-sdk-python/issues/323
- MCP Server Documentation: https://docs.claude.com/en/docs/agent-sdk/mcp