Skip to content

continue_conversation with a session_store continues a local session the store doesn't have #1387

Open

Description

@Somay-kousis

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: "For continue_conversation this 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions