fix(agents): classify embedded prompt lock-changed error as permanent announce failure (fixes #91527)#91641
Conversation
… announce failure (fixes openclaw#91527) When a subagent completion is successfully sent to an external channel but the subsequent transcript mirror fails with EmbeddedPromptLockFileChangedError, the announce retry loop re-sends the completion, causing duplicate messages. Add the lock-changed error pattern to PERMANENT_ANNOUNCE_DELIVERY_ERROR_PATTERNS so the announce delivery layer treats it as terminal instead of retrying, mirroring the pattern established by PR openclaw#89812 in the general outbound path.
|
Codex review: needs real behavior proof before merge. Reviewed June 9, 2026, 3:04 AM ET / 07:04 UTC. Summary PR surface: Source +1, Tests +46. Total +47 across 2 files. Reproducibility: yes. source inspection plus the linked live report gives a high-confidence path: the lock-change error is classified in announce delivery, then a non-terminal failed direct result can flow into fallback or lifecycle retry. I did not run a live Telegram reproduction in this read-only review. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Carry post-send lock-change errors as terminal or already visibly delivered through direct delivery, dispatch, and lifecycle, with regression coverage plus redacted real Telegram or runtime-log proof showing one completion. Do we have a high-confidence way to reproduce the issue? Yes, source inspection plus the linked live report gives a high-confidence path: the lock-change error is classified in announce delivery, then a non-terminal failed direct result can flow into fallback or lifecycle retry. I did not run a live Telegram reproduction in this read-only review. Is this the best way to solve the issue? No. Adding the regex is a plausible inner-retry mitigation, but it is not the best complete fix unless the permanent post-send failure also stops dispatch fallback and lifecycle replay. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against f57c3b55fdc4. Label changesLabel justifications:
Evidence reviewedPR surface: Source +1, Tests +46. Total +47 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
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 re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Summary
EmbeddedPromptLockFileChangedErrorafter a successful outbound send.PERMANENT_ANNOUNCE_DELIVERY_ERROR_PATTERNSinsubagent-announce-delivery.tsdoes not include the lock-changed error, so the announce retry loop classifies it as retriable and re-sends the completion up tomaxAnnounceRetryCounttimes./session file changed while embedded prompt lock was released/itoPERMANENT_ANNOUNCE_DELIVERY_ERROR_PATTERNSso the error is treated as terminal, matching the pattern established by PR fix(outbound): keep channel send durable when transcript mirror fails (#89626) #89812 in the general outbound delivery path.src/agents/subagent-announce-delivery.ts— added one regex pattern to the permanent error arraysrc/infra/outbound/deliver.ts)Reproduction
sessions_spawn(taskName="...", mode="run")with a long-running subagent tasksessions_yieldto wait for the auto-announceEmbeddedPromptLockFileChangedErrorReal behavior proof
Behavior or issue addressed (#91527): When a subagent completion has already been sent to the external channel but the transcript mirror fails with
EmbeddedPromptLockFileChangedError, the announce delivery layer now treats the error as terminal instead of retrying, preventing duplicate message delivery.Real environment tested: Linux, Node 22 —
deliverSlackChannelAnnouncementexercised through the completion delivery path with Gateway and channel send mocksExact steps or command run after this patch:
node scripts/run-vitest.mjs src/agents/subagent-announce-delivery.test.ts src/agents/subagent-announce-dispatch.test.ts src/agents/subagent-registry-lifecycle.test.tsEvidence after fix:
Observed result after fix: The new test case "treats embedded prompt lock-changed error as permanent during completion delivery" verifies that when
callGatewaythrows the lock-changed error during a text completion delivery, the result correctly hasdelivered: falsewith the error message preserved, andsendMessageis never called — confirming no duplicate outbound send.What was not tested: Live Telegram end-to-end delivery with concurrent session modifications was not driven; the fix was validated at the announce delivery unit level with mocked Gateway and channel sends, matching the existing test patterns in the file.
Repro confirmation: The new test case throws the exact error message from the reporter's logs (
session file changed while embedded prompt lock was released: /tmp/session.jsonl) and confirms the result isdelivered: falsewith nosendMessagecall — on origin/main without this patch, the same error would have been classified as retriable and the announce lifecycle would have retried up to 3 times.Risk / Mitigation
Risk: Classifying the lock-changed error as permanent means the subagent completion will not be retried if the transcript mirror fails, potentially losing the completion from the session transcript.
Mitigation: The outbound message has already been sent successfully before the mirror failure (
[telegram] outbound send okappears in logs before the error). The user still receives the completion — only the transcript archival is skipped, and the next turn will naturally include the context.Risk: The regex pattern may match unrelated errors containing the same substring.
Mitigation: The error message is specific (
session file changed while embedded prompt lock was released) and produced by a single code path inEmbeddedPromptLockFileChangedError. The existing permanent patterns in the same array use similar specificity (e.g.,/unsupported channel/i,/chat not found/i).Change Type (select all)
Scope (select all touched areas)
Regression Test Plan
node scripts/run-vitest.mjs src/agents/subagent-announce-delivery.test.tsnode scripts/run-vitest.mjs src/agents/subagent-announce-dispatch.test.tsnode scripts/run-vitest.mjs src/agents/subagent-registry-lifecycle.test.tsReview Findings Addressed
N/A (initial submission)
Linked Issue/PR
Fixes #91527