Skip to content

[claude-cli backend] Auto-invalidate stored CLI session id after AbortError / FailoverError #78785

Description

@Marcus-EH

Summary

The bundled claude-cli backend keeps a Claude stdio process alive per OpenClaw session and reuses it across turns via stored session id. After an AbortError or FailoverError on a turn, OpenClaw retains the stored session id and reuses the same (likely damaged) binary on the next turn. The reused binary frequently accepts the new prompt over stdin but produces no output, hitting the 60s no-output watchdog and surfacing a generic error to the user. The damaged session persists until a manual /reset, daily reset, idle expiry, or transcript deletion cuts it.

Reproduction (observed)

  1. Turn N hits AbortError (e.g., user interrupt during a slow tool call) or FailoverError.
  2. Stored CLI session id is not invalidated.
  3. Turn N+1 (any time later, even hours) reuses the stored id → claude live session reuse.
  4. Binary accepts the prompt over stdin but never emits output.
  5. After 60s of silence, watchdog kills the subprocess with reason=abort, model fallback shows next=none detail=CLI produced no output for 60s and was terminated.
  6. User sees: ⚠️ Something went wrong while processing your request. Please try again, or use /new to start a fresh session.

Concrete log evidence (one occurrence)

22:37:54  [agent/cli-backend] cli exec: provider=claude-cli model=opus
          useResume=true reuse=reusable resumeSession=<redacted-session-id>
22:37:54  [agent/cli-backend] claude live session reuse: provider=claude-cli model=claude-opus-4-6
[146 seconds of complete silence — no chunks, no tools, no output]
22:40:21  [agent/cli-backend] claude live session close: reason=abort
22:40:21  [model-fallback/decision] reason=timeout next=none
          detail=CLI produced no output for 60s and was terminated

Earlier the same day, the same backend hit AbortError. The session id reused at 22:37 was likely the damaged one from that earlier abort.

Existing protections (not sufficient)

  • Phantom-binding check verifies transcript existence before reuse — only catches deleted sessions, not wedged ones.
  • session.reset.idleMinutes cuts the underlying CLI session on idle — preventative but coarse; doesn't react to the actual error signal.

Proposed fix

On any AbortError / FailoverError from a claude-cli backend turn, invalidate the stored resumeSession id for that backend. Next turn spawns a fresh claude binary instead of reusing the damaged one.

Optional refinement: only invalidate when the abort/error happened with useResume=true reuse=reusable (i.e., reusing an existing live session), since fresh-spawn aborts don't taint the next turn.

Workaround today

/reset soft drops the stored CLI session id without clearing the transcript.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions