Skip to content

fix(claude-code): recreate a persisted session the CLI no longer has - #5651

Open
nocstah wants to merge 1 commit into
tinyhumansai:mainfrom
nocstah:fix/cc-session-recreate
Open

fix(claude-code): recreate a persisted session the CLI no longer has#5651
nocstah wants to merge 1 commit into
tinyhumansai:mainfrom
nocstah:fix/cc-session-recreate

Conversation

@nocstah

@nocstah nocstah commented Aug 21, 2026

Copy link
Copy Markdown

Summary

  • Fixes a hard failure where a Claude Code (claude-code) chat thread breaks permanently with No conversation found with session ID: <uuid>.
  • The driver persists a self-minted session id before the creating turn succeeds, then only ever --resumes it — so any first-turn failure poisons the thread with no recovery.
  • Now the driver checks whether the CLI still has the session on disk before choosing --resume, and recreates a missing one with --session-id + full context.

Problem

run_turn in claude_code/driver.rs decides new-vs-resume from session_store alone: a persisted UUID means --resume. But the id is written to claude-code-sessions.json before the creating call runs, so if that call fails (transient error, cancelled turn, or the user's CLI session store is cleared), the id survives but the session was never created. Every later turn then --resumes a session the CLI does not have and exits non-zero with No conversation found with session ID: <uuid>. Restarting the app or model does not help — the mapping is never invalidated.

Reproduced against claude CLI 2.1.237 / model claude-opus-5. Confirmed a shim that rewrites --resume <id>--session-id <id> when the session file is absent makes chat work immediately, i.e. the CLI and model are fine; the driver's create/resume bookkeeping is the bug.

Solution

  • Add cc_session_exists (+ a pure, testable cc_session_exists_in) that scans <CLAUDE_CONFIG_DIR|~/.claude>/projects/*/<id>.jsonl.
  • Treat a persisted id whose session is absent as new: recreate it with the same id (so the thread's mapping stays stable) via --session-id, and send full context (is_new = true) since the CLI holds no prior turns.
  • No behavior change on the healthy path (existing session → --resume as before).

Submission Checklist

  • Tests added or updated — cc_session_exists_in_detects_present_and_absent covers present, absent, and wrong-id cases.
  • Diff coverage ≥ 80% — the new helper is unit-tested; the few changed lines inside run_turn (the new/resume decision) are not directly covered because run_turn spawns a subprocess and has no unit harness. pnpm test:rust passes locally. Happy to add an integration test if reviewers prefer.
  • Coverage matrix updated — N/A: behaviour-only fix, no feature row change.
  • All affected feature IDs listed under ## RelatedN/A.
  • No new external network dependencies introduced.
  • Manual smoke checklist — N/A: does not touch release-cut surfaces.
  • Linked issue closed via Closes #NNN.

Impact

  • Desktop/CLI, Claude Code provider only. Recovers permanently-broken threads and hardens against future first-turn failures. No migration, no new deps.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/cc-session-recreate

Summary by CodeRabbit

  • Bug Fixes
    • Improved Claude Code session resumption by verifying that saved sessions still exist.
    • Missing sessions are now recreated using the existing valid session identifier, avoiding repeated failed resume attempts.
    • Added handling for mismatched session files to improve session reliability.

The claude-code driver mints a session UUID, persists it to
claude-code-sessions.json before the creating turn runs, then uses
--resume on every later turn. If that first create fails (a transient
error, a cancelled turn, a cleared CLI store), the id is already
persisted but the session was never created, so every later turn fails
with "No conversation found with session ID: <uuid>" and there is no
recovery. The thread is poisoned across app and model restarts.

This checks whether the CLI still has the session on disk before
choosing --resume. When the persisted id has no
<config>/projects/*/<id>.jsonl, the turn is treated as new: it recreates
the session (reusing the same id so the thread mapping stays stable) with
--session-id and full context.

Adds cc_session_exists / cc_session_exists_in plus a unit test.

Closes tinyhumansai#5648

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nocstah
nocstah requested a review from a team August 21, 2026 03:34
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ad830a5e-d361-4cb7-82f1-e8457358e573

📥 Commits

Reviewing files that changed from the base of the PR and between 60775aa and 302a38f.

📒 Files selected for processing (1)
  • src/openhuman/inference/provider/claude_code/driver.rs

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The Claude Code driver now verifies that persisted session UUIDs have matching on-disk session files. Missing sessions are recreated with the existing valid UUID. Tests cover absent, matching, and mismatched session files.

Changes

Claude Code session recovery

Layer / File(s) Summary
Session file detection
src/openhuman/inference/provider/claude_code/driver.rs
The driver scans Claude project directories for the requested session JSONL file and returns false when it cannot find one.
Resume recovery and validation
src/openhuman/inference/provider/claude_code/driver.rs
Turn initialization recreates missing sessions with the persisted UUID. The resumable-session assertion and session detection tests reflect this behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: 🔵 Low · up to 302a3

The change recovers Claude Code conversations whose persisted session is missing by recreating the session with its prior context. It is mergeable with explicit owner awareness that concurrent turns for the same conversation could still overlap and cause duplicate or out-of-order transcript updates.

Suggested reviewers: senamakel

Poem

A rabbit checks each session trail,
Through project paths where files prevail.
If one is gone, a new turn starts,
With UUIDs kept in careful hearts.
No stale resume loop hops again. 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: recreating a persisted Claude Code session that the CLI no longer has.
Linked Issues check ✅ Passed The changes address issue #5648 by checking session existence and recreating missing sessions with the persisted ID instead of retrying --resume.
Out of Scope Changes check ✅ Passed The changes remain limited to Claude Code session recovery, helper functions, and focused unit tests related to issue #5648.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 1 files.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tinysweeper

tinysweeper Bot commented Aug 21, 2026

Copy link
Copy Markdown

How this change flows

2 changed behaviours across 1 relationship. The code graph does not know these behaviours yet — normal for newly added code, and a cold index otherwise. 1 further behaviour left out to keep the diagram readable.

flowchart LR
  n0["append_system_prompt_args<br/>changed"]:::changed
  n1["run_turn<br/>changed"]:::changed
  n1 -->|calls| n0
  classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
  classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
  classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
  classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Loading

Green: changed behaviour. Grey: surrounding behaviour. Arrows name the call, use, implementation, or test relationship. Orange: has findings. Red: has a finding that blocks the merge.

tinysweeper 0.1.0

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tinysweeper found nothing blocking. Approving.

$0.0000 · 0 in / 0 out · 234 embedded · openrouter/openai/text-embedding-3-small

@tinysweeper tinysweeper Bot added the priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. label Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[claude-code] Chat fails permanently — driver resumes a session it never created ("No conversation found")

1 participant