Repository navigation
continue_conversation with a session_store continues a local session the store doesn't have #1387
Description
When session_store is set and continue_conversation=True, the SDK picks the session to continue from the store. If the store has nothing to continue, the CLI still gets --continue. It then continues the newest transcript on local disk for that cwd, one the store never had.
With one store per user and a shared cwd, that is another user's conversation.
materialize_resume_session says this case should start fresh:
session_resume.py:138: "Forcontinue_conversationthis means a fresh session"session_resume.py:154: "list_sessions() → fresh session (matches CLI --continue with no history)"
But local disk does have history. Every store-backed session also writes its local transcript.
Repro
Two stores, same cwd. Alice talks first. Bob's store is empty and he asks to continue.
import anyio
from claude_agent_sdk import query, ClaudeAgentOptions, InMemorySessionStore
BASE = dict(model="haiku", setting_sources=[], strict_mcp_config=True, max_turns=1)
async def run(store, prompt, **kw):
sid = text = None
async for m in query(prompt=prompt, options=ClaudeAgentOptions(session_store=store, **BASE, **kw)):
if type(m).__name__ == "ResultMessage":
sid, text = m.session_id, m.result
return sid, text
async def main():
alice = InMemorySessionStore()
a_sid, _ = await run(alice, "Remember this secret word: PELICAN. Reply only with ok.")
bob = InMemorySessionStore() # a different user's store, empty
b_sid, text = await run(bob, "If you know a secret word from earlier, say it. Otherwise say NONE.", continue_conversation=True)
print("bob continued alice's session:", b_sid == a_sid)
print("bob got answer:", text)
anyio.run(main)Output on main (df6940a, SDK 0.2.166, Claude Code 2.1.294):
bob continued alice's session: True
bob got answer: PELICAN
Expected: Bob gets a new session and the answer NONE.
Bob's store also starts receiving the rest of Alice's session under her session id.
It happens whenever the store has no session to continue: empty store, a store for another tenant, or one holding only sidechains.
Root cause
materialize_resume_session returns None when the store has no candidate (_internal/session_resume.py:152-164). Both entry points then fall through with the options unchanged (_internal/client.py:51-53, client.py:125-129). continue_conversation is still True, and _build_command passes it on (_internal/transport/subprocess_cli.py:639-640):
if self._options.continue_conversation:
cmd.append("--continue")When the store does have a session, apply_materialized_options sets continue_conversation=False and resume=<id>. So with a store, continue_conversation still being True at spawn means the store had nothing to continue.
Fix
Don't pass --continue when session_store is set. The store path already turned a real continue into --resume. PR to follow.
Activity