Query.close() cancels the task group and closes the transport but leaves other resources uncleaned. The memory object stream objects are reported as leaked from the following simple reproduction script when run with PYTHONDEVMODE defined. This is likely fixed by #657. I decided to create the issue to boost awareness.
#!/usr/bin/env python3
"""
Reproduces the ResourceWarning for unclosed anyio memory streams in Query.close().
Query.close() cancels the read task and closes the transport but never calls
aclose() on self._message_send or self._message_receive (the anyio
MemoryObjectSendStream / MemoryObjectReceiveStream pair created in __init__).
Those objects are collected by the GC with their streams still open.
Usage:
PYTHONDEVMODE=1 python repro_stream_leak.py
Expected warnings:
ResourceWarning: Unclosed <MemoryObjectReceiveStream ...>
ResourceWarning: Unclosed <MemoryObjectSendStream ...>
"""
import asyncio
import gc
import claude_agent_sdk
async def main() -> None:
async with claude_agent_sdk.ClaudeSDKClient() as client:
await client.query("Reply with the single word: hello")
async for _message in client.receive_response():
pass
asyncio.run(main())
# Force GC so the warnings are emitted during the script rather than at
# interpreter shutdown, where they can be swallowed or harder to attribute.
gc.collect()
Query.close() cancels the task group and closes the transport but leaves other resources uncleaned. The memory object stream objects are reported as leaked from the following simple reproduction script when run with
PYTHONDEVMODEdefined. This is likely fixed by #657. I decided to create the issue to boost awareness.