SDK subprocess hangs on initialize, leaving zombie processes that block subsequent connections
Resolved 💬 1 comment Opened Jan 16, 2026 by banddude Closed Jan 16, 2026
Environment
- claude-agent-sdk version: 0.1.18
- Claude Code CLI version: 2.1.9
- Python: 3.10.13
- OS: macOS (Darwin)
- Auth: CLAUDE_CODE_OAUTH_TOKEN (subscription-based)
Bug Description
When using ClaudeSDKClient to connect, the SDK spawns a claude --output-format stream-json subprocess but the initialization handshake times out after 60 seconds with "Control request timeout: initialize".
Each failed attempt leaves a zombie claude process running at 60-70% CPU. These accumulated zombie processes appear to block subsequent connection attempts.
Symptoms
await client.connect()times out with "Control request timeout: initialize"- Zombie processes accumulate:
claude --output-format stream-json --verbose ... - After killing zombie processes, the next connection attempt succeeds
- The CLI works perfectly when called directly:
echo "hi" | claude --print --model opus
Reproduction Steps
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
import asyncio
async def test():
options = ClaudeAgentOptions(
cwd="/path/to/dir",
permission_mode="bypassPermissions",
extra_args={"model": "opus", "mcp-config": "/path/to/.mcp.json"}
)
client = ClaudeSDKClient(options=options)
await asyncio.wait_for(client.connect(), timeout=60) # Times out
asyncio.run(test())
Workaround
Kill zombie processes before retrying:
pkill -9 -f "claude.*stream-json"
Expected Behavior
- SDK should connect successfully
- Failed connections should clean up subprocess properly
- Zombie processes should not accumulate
Actual Behavior
- Connection times out waiting for initialize response
- Subprocess remains running as zombie
- Subsequent attempts fail until zombies are killed
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗