Skip to content

fix(agents): clear stale CLI session binding for all FailoverError reasons (#77089)#77385

Closed
hclsys wants to merge 2 commits into
openclaw:mainfrom
hclsys:fix/77089-cli-session-failover-v2
Closed

fix(agents): clear stale CLI session binding for all FailoverError reasons (#77089)#77385
hclsys wants to merge 2 commits into
openclaw:mainfrom
hclsys:fix/77089-cli-session-failover-v2

Conversation

@hclsys

@hclsys hclsys commented May 4, 2026

Copy link
Copy Markdown

Problem

attempt-execution.ts only cleared the persisted CLI session binding from the store when err.reason === "session_expired". When a FailoverError with reason auth, billing, or rate_limit was thrown (either as the primary error or as a secondary error after cli-runner.ts's internal session_expired retry), the stale binding was left in the store. The next turn would try to resume the same dead CLI session and fail again.

Fix

Clear the stale binding unconditionally for any FailoverError that has an activeCliSessionBinding. Then:

  • Recoverable (session_expired, timeout, unknown): clear binding + retry with a fresh session
  • Non-recoverable (auth, billing, rate_limit): clear binding + rethrow immediately so the caller surfaces the real error

This also covers the case where cli-runner.ts's internal session_expired retry succeeds with a fresh session but fails on a subsequent FailoverError (e.g. auth): attempt-execution.ts receives the secondary error, correctly clears the original stale binding, and rethrows.

Changes

  • src/agents/command/attempt-execution.ts: widen the FailoverError gate from session_expired-only to any FailoverError; add rethrow-without-retry path for non-recoverable reasons
  • src/agents/command/attempt-execution.cli.test.ts: add test for non-recoverable path (auth reason) — verifies binding is cleared (prevents dead-session resume) but no retry is attempted
  • CHANGELOG.md: entry for fix(agents): clear stale CLI session on any FailoverError, not only session_expired #77141

Test

pnpm test src/agents/command/attempt-execution.cli.test.ts

17/17 pass.

pnpm exec oxfmt --check --threads=1 src/agents/command/attempt-execution.ts src/agents/command/attempt-execution.cli.test.ts CHANGELOG.md

0 errors.

Fixes #77089.

Real behavior proof

  • Behavior or issue addressed: CLI failover now clears the stale persisted CLI session binding for every FailoverError reason before rethrowing non-recoverable errors, so the next CLI turn does not retry a dead session id.
  • Real environment tested: Local OpenClaw checkout on branch fix/77089-cli-session-failover-v2 after rebasing onto origin/main 9c4a335007; Node/Vitest project runner from this repository.
  • Exact steps or command run after this patch: pnpm test src/agents/command/attempt-execution.cli.test.ts
  • Evidence after fix: Terminal output from the after-patch run:
[test] starting test/vitest/vitest.agents.config.ts
Test Files  1 passed (1)
Tests  19 passed (19)
[test] passed 1 Vitest shard in 6.14s
  • Observed result after fix: The CLI attempt-execution regression shard passed, including the failover paths that clear the stale CLI session binding across FailoverError reasons.
  • What was not tested: Live provider auth/billing failures were not invoked against an external model provider; the verification used the repo's CLI execution path regression coverage.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels May 4, 2026
@clawsweeper

clawsweeper Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge.

Summary
The PR widens CLI FailoverError handling in attempt-execution.ts, adds mocked CLI attempt regression tests for auth/timeout/unknown stale-session cleanup, and adds a changelog entry.

Reproducibility: yes. Source inspection gives a high-confidence path: current main only clears stale CLI bindings for session_expired, while the CLI execution layer can raise timeout and unknown FailoverError reasons from the same resumed-session path.

Real behavior proof
Needs real behavior proof before merge: Needs real behavior proof before merge: the PR body shows after-patch Vitest output, but no real CLI/backend run or redacted runtime logs showing stale-session recovery.

Next step before merge
Contributor or maintainer follow-up is needed for real CLI/backend proof and a hook-aware retry revision; this should not be sent to an automated repair lane while proof is mock-only.

Security
Cleared: The diff only changes agent error handling, regression tests, and changelog text; no security or supply-chain concern was found.

Review findings

  • [P2] Keep recoverable retry inside the CLI runner lifecycle — src/agents/command/attempt-execution.ts:535-539
Review details

Best possible solution:

Keep the store cleanup for every resumed-session FailoverError, but move recoverable fresh-session retry under the CLI runner hook lifecycle or an equivalent hook-aware seam before merge.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection gives a high-confidence path: current main only clears stale CLI bindings for session_expired, while the CLI execution layer can raise timeout and unknown FailoverError reasons from the same resumed-session path.

Is this the best way to solve the issue?

No. The cleanup boundary is right, but retrying timeout/unknown from attempt-execution.ts is not the narrowest maintainable fix because it runs after the CLI runner can emit a failed final hook event.

Full review comments:

  • [P2] Keep recoverable retry inside the CLI runner lifecycle — src/agents/command/attempt-execution.ts:535-539
    By treating timeout and unknown as recoverable here, the outer catch retries after runCliAgent has already emitted agent_end with success: false. If the fresh retry succeeds, hook consumers observe a failed final state while the caller returns success, so the recoverable retry needs to move under the CLI runner lifecycle or an equivalent hook-aware seam.
    Confidence: 0.88

Overall correctness: patch is incorrect
Overall confidence: 0.88

What I checked:

Likely related people:

  • steipete: Current-main blame for the affected attempt-execution and cli-runner failover blocks points to Peter Steinberger, and GitHub commit history shows repeated recent maintenance across the affected agent/session files. (role: recent maintainer and likely follow-up owner; confidence: high; commits: a34d4ef9d9, 82c11deaa2cb, fa689295c649; files: src/agents/command/attempt-execution.ts, src/agents/cli-runner.ts, src/agents/command/session-store.ts)
  • vincentkoc: Recent merged work hardened CLI runner hooks and transcript loading around the same agent_end/history surface that this PR can regress. (role: adjacent hook behavior owner; confidence: medium; commits: f40f8a60cce5, 51f9f94cc361; files: src/agents/cli-runner.reliability.test.ts)
  • HFConsultant: Introduced the atomic CLI session clearing path and regression coverage that this PR relies on when clearing stale persisted bindings. (role: session-store cleanup history; confidence: medium; commits: 647f4ee8ce4f; files: src/agents/command/session-store.ts, src/agents/command/session-store.test.ts)
  • wenxu007: Recently worked on FailoverError propagation through the CLI/failover path, which is adjacent to the reasons and metadata this PR changes. (role: failover error attribution history; confidence: medium; commits: 9df0ae676723; files: src/agents/cli-runner.ts, src/agents/cli-runner.reliability.test.ts)

Remaining risk / open question:

  • No real CLI/backend run or redacted runtime logs currently prove stale-session recovery after the patch; the supplied proof is mocked Vitest output.

Codex review notes: model gpt-5.5, reasoning high; reviewed against c3a0fb9325c9.

@hclsys

This comment was marked as low quality.

@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label May 5, 2026
…asons (openclaw#77141)

Previously, `attempt-execution.ts` only cleared the CLI session store entry
when the FailoverError reason was session_expired, timeout, or unknown.
Auth/billing errors skipped the clear, so the next turn would try to resume
a dead CLI session and fail again.

Now the binding is cleared for any FailoverError with an active binding.
Recoverable reasons (session_expired, timeout, unknown) still retry fresh;
non-recoverable reasons (auth, billing, rate_limit) rethrow immediately so
the caller can surface the real error to the user.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label May 5, 2026
P2: add timeout and unknown recovery tests to prove cleared binding +
fresh retry behavior, matching the existing session_expired test pattern.
Also tighten comment in attempt-execution.ts to clarify the retry logic.

P3: fix changelog to reference openclaw#77385 (this PR) and openclaw#77089 (bug), not
the closed unmerged openclaw#77141.

19/19 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@hclsys

This comment was marked as low quality.

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

Labels

agents Agent runtime and tooling size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI backend: retry fresh session on any FailoverError, not just session_expired

1 participant