Skip to content

Don't mutate caller message dicts in ClaudeSDKClient.query()#1129

Open
winklemad wants to merge 1 commit into
anthropics:mainfrom
winklemad:fix-query-mutates-caller-message-session-id
Open

Don't mutate caller message dicts in ClaudeSDKClient.query()#1129
winklemad wants to merge 1 commit into
anthropics:mainfrom
winklemad:fix-query-mutates-caller-message-session-id

Conversation

@winklemad

Copy link
Copy Markdown

The AsyncIterable prompt path in ClaudeSDKClient.query() did msg["session_id"] = session_id, injecting the id into the caller's own message dicts. Because the key is then already present, reusing the same message objects in a later query() with a different session_id leaves the original id in place — so the SDK silently sends the stale session id and ignores the session_id argument.

Reachable via the public ClaudeSDKClient.query(prompt=<async iterable>, session_id=...): every such call mutates caller-owned data, and on reuse the wrong session id goes on the wire.

Fix copies the dict before injecting (msg = {**msg, "session_id": ...}). Adds a regression test (test_query_does_not_mutate_caller_messages) covering both no-mutation and honoring session_id on reuse, verified in asyncio and trio.

The AsyncIterable prompt path injected session_id straight into each
message dict yielded by the caller's iterable. Beyond the unexpected
side effect on caller-owned data, it broke reuse: passing the same
messages to query() again with a different session_id left the original
id in place (the "session_id" key was already present), so the second
call silently sent the stale id and ignored its session_id argument.

Build a shallow copy before injecting session_id instead of mutating the
caller's dict.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant