-
Notifications
You must be signed in to change notification settings - Fork 561
Description
Description
ClaudeSDKClient hangs indefinitely during initialization on Windows when entering the async context manager. The SDK successfully spawns the Claude CLI subprocess but never receives the expected control_response to the initialization request, causing it to timeout after 60 seconds.
Environment
- OS: Windows 11
- Python Version: 3.13
- claude-agent-sdk Version: Latest
- Claude CLI Version: 2.0.8
- Shell: PowerShell / Git Bash
Steps to Reproduce
import asyncio
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
async def main():
options = ClaudeAgentOptions(
model="sonnet",
permission_mode="acceptEdits",
)
print("Initializing...")
async with ClaudeSDKClient(options=options) as client:
print("Client ready!") # Never reaches here
await client.query("Hello")
async for msg in client.receive_response():
print(msg)
asyncio.run(main())Expected Behavior
The client should initialize successfully and print "Client ready!" within a few seconds.
Actual Behavior
The script hangs at the async with ClaudeSDKClient(options=options) line for 60 seconds, then fails with:
Fatal error in message reader: Command failed with exit code 143 (exit code: 143)
Error output: Check stderr output for details
Root Cause Analysis
Investigation shows:
-
The SDK successfully spawns the Claude CLI subprocess with arguments like:
claude --output-format stream-json --verbose --model sonnet --input-format stream-json --permission-mode acceptEdits --setting-sources "" -
The SDK sends an initialization control request via stdin:
{"type":"control_request","request_id":"req_1_...","request":{"subtype":"initialize"}} -
The CLI subprocess never responds with a
control_response, causingQuery.initialize()to hang waiting for the response (line 309-310 in_internal/query.py). -
Testing the exact same command manually in Git Bash/PowerShell works correctly:
echo '{"type":"control_request","request_id":"test123","request":{"subtype":"initialize"}}' | claude --output-format stream-json --verbose --model sonnet --input-format stream-json --permission-mode acceptEdits --setting-sources ""
This immediately returns the expected
control_response. -
The issue appears to be Windows-specific subprocess stdin/stdout buffering or communication issues when spawning the process via Python's
anyio.open_process().
Workaround
The issue does not occur when running the same code in WSL (Windows Subsystem for Linux).
Additional Context
- The
query()function works fine on Windows (non-interactive mode) - Only
ClaudeSDKClient(interactive/streaming mode) is affected - The subprocess is successfully spawned but the bidirectional communication fails
- Stderr capture shows no output from the CLI subprocess
Suggested Fix
This may require Windows-specific handling of subprocess pipes, possibly:
- Setting appropriate buffer modes for stdin/stdout
- Using different process creation flags on Windows
- Ensuring stdin is properly flushed after writing
- Investigating if
anyio.open_process()has known Windows issues with stdin/stdout pipes