Skip to content

fix(acp): recover stale persistent sessions by structured resume-required code [AI-assisted]#93547

Merged
openclaw-clownfish[bot] merged 1 commit into
openclaw:mainfrom
amersheeny:fix/acp-session-resume-structured-detailcode
Jun 22, 2026
Merged

fix(acp): recover stale persistent sessions by structured resume-required code [AI-assisted]#93547
openclaw-clownfish[bot] merged 1 commit into
openclaw:mainfrom
amersheeny:fix/acp-session-resume-structured-detailcode

Conversation

@amersheeny

@amersheeny amersheeny commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #87830 — thread-bound persistent ACP sessions stop replying on the second turn for Kiro.

When a backend can no longer resume a stale persistent session, acpx raises a SessionResumeRequiredError whose reason text varies by backend: Claude reports "Resource not found", Kiro reports "Internal error" (RequestError -32603). OpenClaw's recovery gate (manager.runtime-resume-state.ts) matched the human reason text and required "resource not found", so Kiro's "Internal error" never triggered the fresh-session retry — the turn failed with ACP_TURN_FAILED and the thread produced no reply, while Claude (whose reason happened to match the regex) recovered.

Root cause is deeper than the reason text: acpx tags every such failure with the structured contract detailCode: "SESSION_RESUME_REQUIRED" (retryable: true), independent of wording. But the two AcpRuntimeError construction seams (consumeAcpTurnEvents, errorFromTurnResult) were discarding detailCode, leaving the gate no choice but to parse the message.

The fix:

  1. Preserve detailCode on AcpRuntimeError (additive optional field) so structured failure data isn't thrown away at construction.
  2. Thread detailCode through both seams.
  3. Match SESSION_RESUME_REQUIRED structurally across the error and its cause chain, instead of the reason regex.

This recovers every backend's resume-required failure (not just the two observed reasons) and is more precise than the old regex — a generic "Internal error" without the structured code is surfaced rather than silently retried.

Relationship to #93315

#93315 (@xialonglee) targets the same bug by extending the message regex to also match SessionResumeRequiredError / session resume required. That approach cannot match the real failure: acpx builds the message as `Persistent ACP session ${id} could not be resumed: ${reason}` (acpx dist live-checkpoint, makeSessionResumeRequiredError), so the AcpRuntimeError.message reaching the gate is "Persistent ACP session … could not be resumed: Internal error" — the SessionResumeRequiredError string is the error's .name, never in the message (the seams use normalizeText(event.message) / normalizeText(result.error.message), the raw message, not the formatAcpErrorChain rendering). #93315's retry test passes only because it manually concatenates " <- SessionResumeRequiredError: …" into the test event message — a string the real pipeline does not emit. Keying on the structured detailCode avoids depending on message wording entirely.

AI-assisted (Claude Code), directed and reviewed by the PR author.

Real behavior proof

Behavior addressed: a thread-bound persistent ACP turn whose backend reports a resume-required failure with reason "Internal error" (Kiro / RequestError -32603) now discards the stale persistent identity and retries with a fresh session, instead of failing the turn (#87830).

Real environment tested: macOS (Darwin), Node 22, the real AcpSessionManager turn runner exercised end-to-end through manager.runTurn with the actual recovery path (prepareFreshManagerRuntimeHandleRetryensureSession). The failure reproduces fully at the manager boundary: the recovery code is pure error-classification and makes no backend/Bot-API call, so a mocked runtime emitting the exact acpx error shape (detailCode: "SESSION_RESUME_REQUIRED", message "…could not be resumed: Internal error") drives the real production path.

Exact steps or command run after this patch:

  1. node scripts/run-vitest.mjs src/acp/control-plane/manager.turn-results.test.ts
  2. Revert the three source files to origin/main and re-run to confirm the new cases fail without the fix.

Evidence after fix: copied live command output.

With the fix — all cases pass (the two resume-required reasons, the thrown-cause shape, and the negative precision case):

Tests  18 passed (18)

Reverting the source (matcher + seams + AcpRuntimeError) to origin/main, the Kiro "Internal error" and thrown-cause cases fail while the happy-path and precision cases still pass — proving the new behavior:

×  retries with a fresh persistent session on a resume-required error: Internal error (Kiro RequestError -32603)
×  recovers when the resume-required error is wrapped as a thrown cause
Tests  2 failed | 16 passed (18)
Caused by: AcpRuntimeError: Persistent ACP session acpx-sid-stale could not be resumed: Internal error

Dependency contract verified directly in node_modules/acpx dist: SessionResumeRequiredError extends AcpxOperationalError with detailCode: "SESSION_RESUME_REQUIRED", retryable: true; the message is `Persistent ACP session ${id} could not be resumed: ${reason}`.

Observed result after fix: the manager calls prepareFreshSession, re-runs ensureSession with resumeSessionId undefined, the session identity is replaced with the fresh backend id, and the turn completes; session state transitions running→idle with no error.

What was not tested: the full gateway/chat surface (channel → gateway → manager) end-to-end. The resume failure and recovery themselves were validated live against a real kiro-cli backend through the real acpx runtime and the real manager seams (consumeAcpTurnStreamprepareFreshManagerRuntimeHandleRetry) — see "Live Kiro backend proof" below — not mocked.

Live Kiro backend proof

Reproduced the failure and recovery against a real, logged-in kiro-cli 2.8.1 (free AWS Builder ID) — no mock backend.

Backend (raw ACP over stdio). A session is created in one kiro-cli acp process; that process is killed (gateway restart); a fresh kiro-cli acp asked to session/load it rejects with the exact #87830 shape:

session/load REJECTED: { "name":"RequestError", "code": -32603,
  "message": "Internal error",
  "data": "Failed to start session: Session not found: <session-id>" }

Kiro advertises agentCapabilities.loadSession: true, so acpx does attempt the reconnect — and the rejection is -32603 "Internal error", not Claude's "Resource not found".

End-to-end (real acpx runtime + real manager seams). Turn 1 creates a persistent Kiro session with a real agent message (non-fallback-safe); a fresh acpx runtime sharing the same on-disk session store runs turn 2 → acpx reconnect → live Kiro -32603 → real consumeAcpTurnStream → real prepareFreshManagerRuntimeHandleRetry:

{ "kiroVersion": "kiro-cli 2.8.1",
  "turn2RuntimeError": [{ "type":"error", "code":"ACP_TURN_FAILED",
    "detailCode":"SESSION_RESUME_REQUIRED", "retryable":true,
    "message":"Persistent ACP session <id> could not be resumed: Internal error" }],
  "turn2ThrownError": { "instanceofAcpRuntimeError":true, "code":"ACP_TURN_FAILED",
    "detailCode":"SESSION_RESUME_REQUIRED" },
  "recovery": { "retry":true, "identityDowngradedTo":"pending", "runtimeHandleClearedAfter":true },
  "negativeControl": { "message":"…could not be resumed: Internal error", "detailCode":null, "retry":false } }

Negative control: the same human message with detailCode stripped → retry: false. Recovery fires on acpx's structured SESSION_RESUME_REQUIRED, never the reason text — which is exactly why the old text-match missed Kiro. (Live harness available on request.)

Verification

  • node scripts/run-vitest.mjs src/acp/control-plane/manager.turn-results.test.ts — 18 passed (4 new cases).
  • ACP control-plane + acp-core runtime suites pass (manager.test, manager.failover, manager.backend-failover, manager.initialize-session, manager.startup-identity-reconcile, acp-core/runtime/errors, error-text).
  • New regression cases fail against origin/main's source and pass with the fix (verified by reverting the three source files).
  • Live recovery validated against real kiro-cli 2.8.1 (raw ACP -32603 repro + real acpx runtime through the real manager seams; run locally, not in CI).
  • tsgo:core + tsgo:core:test green; oxlint/oxfmt clean; pnpm build green.

Release-note context: persistent ACP threads (notably Kiro) no longer get permanently stuck after a stale-session resume failure; recovery now keys on acpx's structured resume-required code rather than the backend's reason wording. Reported by @chouzz in #87830.

@openclaw-barnacle openclaw-barnacle Bot added the proof: supplied External PR includes structured after-fix real behavior proof. label Jun 16, 2026
@amersheeny
amersheeny force-pushed the fix/acp-session-resume-structured-detailcode branch 2 times, most recently from 2244a98 to 0ae0761 Compare June 16, 2026 09:35
@amersheeny

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

The automated review doesn't appear to have triggered for this PR. CI is fully green and the branch is mergeable/clean — could you run the review? Thanks.

@clawsweeper

clawsweeper Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@amersheeny

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

The prior re-review failed waiting for Codex capacity (run 27612067178). CI is fully green and the branch is mergeable/clean — retrying now that capacity should have recovered.

@amersheeny

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Two earlier attempts failed waiting for Codex capacity (last at 13:07 UTC, ~5h ago). Retrying now that capacity has had time to recover. CI is fully green (137 checks) and the branch is mergeable/clean.

@clawsweeper

clawsweeper Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 21, 2026, 8:21 PM ET / 00:21 UTC.

Summary
The branch preserves ACP runtime detailCode, forwards it through turn failure seams, and uses SESSION_RESUME_REQUIRED to trigger fresh persistent-session retry with regression coverage.

PR surface: Source +29, Tests +41. Total +70 across 4 files.

Reproducibility: yes. at source level: current main and v2026.6.9 only recover stale persistent ACP resume messages containing resource not found or no matching session, while the linked report and acpx contract show Kiro's Internal error with SESSION_RESUME_REQUIRED. I did not rerun live Kiro in this read-only review, but the PR body includes live backend and manager-seam output.

Review metrics: 3 noteworthy metrics.

  • Recovery Predicate: 1 classifier replaced. This predicate decides when OpenClaw clears stale persisted ACP identity and replays a user turn.
  • Turn Failure Seams: 2 seams updated. Both streaming error events and failed turn results need to preserve detailCode for current ACP runtime paths.
  • ACP Runtime Error Contract: 1 optional field added. AcpRuntimeError is exported through ACP runtime surfaces, so maintainers should notice the additive structured error contract.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #87830
Summary: The linked Kiro stale persistent ACP session issue is the canonical report, and this PR is the active structured-code fix candidate; earlier regex PRs were closed in favor of it.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • [P1] Existing or third-party ACP runtime implementations that only produce the shipped text-shaped stale-resume message without detailCode would stop using the stale-session recovery path.
  • [P1] The retry clears persisted ACP resume identity and replays the user's turn once before any output, which can change session state and message-delivery behavior.
  • [P1] The proof reaches live Kiro/acpx manager seams but does not show a full channel-to-gateway visible chat round trip of the original no-reply symptom recovering.

Maintainer options:

  1. Accept structured retry semantics (recommended)
    Merge after a maintainer accepts acpx SESSION_RESUME_REQUIRED as the recovery signal and accepts the disclosed one-time replay behavior.
  2. Keep a legacy text fallback
    Preserve the old resource not found and no matching session fallback with focused tests if maintainers require compatibility for runtimes that do not emit detailCode.
  3. Request full chat proof
    Pause for a redacted channel-to-gateway Kiro thread proof if maintainers want transport-visible evidence before accepting the replay and session-state risk.

Next step before merge

  • Maintainer review should decide whether to accept the structured retry semantics and disclosed session/message-delivery risk; no automated repair is identified.

Security
Cleared: The diff changes ACP runtime error propagation, retry classification, and tests only; it does not touch dependencies, workflows, package scripts, secrets, permissions, or code-loading surfaces.

Review details

Best possible solution:

Land the structured SESSION_RESUME_REQUIRED recovery after maintainer acceptance of the compatibility and one-time replay risk, then close the linked Kiro stale-session issue once merged.

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

Yes, at source level: current main and v2026.6.9 only recover stale persistent ACP resume messages containing resource not found or no matching session, while the linked report and acpx contract show Kiro's Internal error with SESSION_RESUME_REQUIRED. I did not rerun live Kiro in this read-only review, but the PR body includes live backend and manager-seam output.

Is this the best way to solve the issue?

Yes: preserving and matching acpx's structured detailCode is narrower and more maintainable than expanding backend reason-text regexes, and the PR covers both event and failed-result seams. The remaining question is maintainer acceptance of compatibility and replay semantics, not a concrete code defect.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 1f6ae32cabb9.

Label changes

Label justifications:

  • P1: The linked bug can leave thread-bound ACP conversations processing messages without returning a normal reply.
  • merge-risk: 🚨 compatibility: The PR replaces shipped message-text stale-session matching with a structured-detail requirement that may affect runtimes lacking detailCode.
  • merge-risk: 🚨 session-state: The PR changes the condition that clears stale persisted ACP resume identity and creates a fresh persistent session.
  • merge-risk: 🚨 message-delivery: The recovery path can replay the user's turn once, affecting whether a stuck thread returns a normal reply or fails.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes copied live Kiro backend output, real acpx runtime plus manager-seam recovery output, and a negative control showing recovery depends on detailCode.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied live Kiro backend output, real acpx runtime plus manager-seam recovery output, and a negative control showing recovery depends on detailCode.
Evidence reviewed

PR surface:

Source +29, Tests +41. Total +70 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 3 37 8 +29
Tests 1 76 35 +41
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 113 43 +70

What I checked:

  • Current main misses Kiro stale-resume wording: Current main only retries persistent ACP resume failures when the message contains the persistent-session wrapper plus resource not found or no matching session, so the reported Kiro Internal error shape is still not recovered on main. (src/acp/control-plane/manager.runtime-resume-state.ts:20, 1f6ae32cabb9)
  • Current main drops structured detail on thrown turn errors: Current main constructs AcpRuntimeError from stream events and failed turn results with code and message only, even though the runtime contract already includes optional detailCode. (src/acp/control-plane/manager.turn-stream.ts:42, 1f6ae32cabb9)
  • PR uses structured recovery signal: The PR changes the stale persistent-session predicate to walk the error/cause chain for SESSION_RESUME_REQUIRED and updates both streaming-event and failed-result seams to preserve detailCode. (src/acp/control-plane/manager.runtime-resume-state.ts:20, 762f574ebd15)
  • Dependency contract supports the structured code: The inspected [email protected] package defines SessionResumeRequiredError with detailCode: "SESSION_RESUME_REQUIRED" and retryable: true, while the human message is Persistent ACP session ... could not be resumed: <reason>. ([email protected]/package/dist/live-checkpoint-CuFft_Nd.js:91)
  • Regression coverage targets the intended behavior: The PR adds positive cases for SESSION_RESUME_REQUIRED with both Claude and Kiro reason text, a thrown-cause shape, and a negative generic Internal error case without the detail code. (src/acp/control-plane/manager.turn-results.test.ts:1050, 762f574ebd15)
  • Latest release still has the old behavior: v2026.6.9 still has the message-text recovery gate and still drops detailCode when constructing thrown turn errors, so this fix is not already shipped. (src/acp/control-plane/manager.runtime-resume-state.ts:20, c645ec4555c0)

Likely related people:

  • steipete: Recent GitHub history shows ACP runtime resume-state extraction, terminal-result handling, and ACP core extraction on the central files/contracts involved in this retry path. (role: recent ACP control-plane and ACP core contributor; confidence: high; commits: 90329e28483f, 635b947e32e0, 77f1359612f6; files: src/acp/control-plane/manager.runtime-resume-state.ts, src/acp/control-plane/manager.turn-stream.ts, packages/acp-core/src/runtime/errors.ts)
  • vincentkoc: Recent history touches ACP turn-stream helper typing and ACPX runtime behavior, and a member comment closed a competing regex PR in favor of this structured-code candidate. (role: recent adjacent ACPX/runtime contributor and reviewer; confidence: medium; commits: f9439715e99b, dfb44912ed28; files: src/acp/control-plane/manager.turn-stream.ts, extensions/acpx/src/runtime.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jun 16, 2026
…ired code

Persistent ACP threads died on the second turn for Kiro: when the backend
can no longer resume a stale session, acpx raises a SessionResumeRequiredError
whose reason text varies by backend ("Resource not found" for Claude,
"Internal error" / RequestError -32603 for Kiro). The recovery gate matched
the human reason text and required "resource not found", so Kiro's "Internal
error" never triggered the fresh-session retry and the thread produced no
reply (ACP_TURN_FAILED).

Recover by acpx's structured detail code instead of the reason text: acpx
tags every such failure with detailCode "SESSION_RESUME_REQUIRED"
(retryable), independent of wording. The two AcpRuntimeError construction
seams were discarding detailCode, so preserve it on AcpRuntimeError and match
it across the error and its cause chain. This fixes every backend's
resume-required failure and is more precise than the reason regex — a generic
"Internal error" without the code is still surfaced rather than silently
retried.

Fixes openclaw#87830. Reported by @chouzz.
@amersheeny
amersheeny force-pushed the fix/acp-session-resume-structured-detailcode branch from 0ae0761 to 762f574 Compare June 17, 2026 07:34
@amersheeny

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Rebased onto current main (was ~393 commits behind); new head 762f574ebd is fully green (139 checks, 0 failures). Same single commit, replayed cleanly — no behavior change from the SHA last reviewed (0ae0761a). The live-Kiro real-behavior-proof gap noted in the prior verdict is unchanged and remains a maintainer judgment (your option 2), as disclosed in the PR body.

@clawsweeper

clawsweeper Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@amersheeny

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Retrying — the prior re-review on this SHA failed on Codex capacity, not on the change. Head is green (0 failures) and the diff is identical to the last verdict's commit. Please re-run when a slot is free.

@amersheeny

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

The previous run got a Codex slot and the review itself succeeded, but it failed at the "Publish event result and apply safe close" step — so the ack has been stuck at "Review in progress" since ~10:08 UTC with the verdict generated but never posted, and no reschedule followed (publish failures don't re-enter the capacity-retry loop). Re-triggering so the verdict can publish; capacity is free now, so this should complete rather than wait.

@amersheeny

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Live Kiro backend proof added to the PR body (new "## Live Kiro backend proof" section), addressing the [P1] "needs real behavior proof before merge" gate:

  • Backend: real kiro-cli 2.8.1 (Builder ID), raw ACP over stdio — a cross-process session/load after the session's process is gone rejects with the exact [Bug]: Persistent ACP session resume fails for Kiro threads after backend invalidation #87830 shape: code: -32603, message: "Internal error", data: "…Session not found". Kiro advertises loadSession: true, so acpx does attempt the reconnect.
  • End-to-end: real acpx runtime + the real manager seams (consumeAcpTurnStreamprepareFreshManagerRuntimeHandleRetry) recover on the live -32603detailCode: "SESSION_RESUME_REQUIRED"retry: true, persisted identity downgraded to pending, runtime handle cleared.
  • Negative control: same human message with detailCode stripped → retry: false — confirms recovery keys on the structured code, not the reason text (which is why the old text-match missed Kiro).

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 19, 2026
@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jun 19, 2026
@openclaw-clownfish
openclaw-clownfish Bot merged commit b843438 into openclaw:main Jun 22, 2026
214 of 225 checks passed
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 23, 2026
…ired code (openclaw#93547)

Persistent ACP threads died on the second turn for Kiro: when the backend
can no longer resume a stale session, acpx raises a SessionResumeRequiredError
whose reason text varies by backend ("Resource not found" for Claude,
"Internal error" / RequestError -32603 for Kiro). The recovery gate matched
the human reason text and required "resource not found", so Kiro's "Internal
error" never triggered the fresh-session retry and the thread produced no
reply (ACP_TURN_FAILED).

Recover by acpx's structured detail code instead of the reason text: acpx
tags every such failure with detailCode "SESSION_RESUME_REQUIRED"
(retryable), independent of wording. The two AcpRuntimeError construction
seams were discarding detailCode, so preserve it on AcpRuntimeError and match
it across the error and its cause chain. This fixes every backend's
resume-required failure and is more precise than the reason regex — a generic
"Internal error" without the code is still surfaced rather than silently
retried.

Fixes openclaw#87830. Reported by @chouzz.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Persistent ACP session resume fails for Kiro threads after backend invalidation

1 participant