Skip to content

fix(outbound): keep channel send durable when transcript mirror fails (#89626)#89812

Merged
clawsweeper[bot] merged 2 commits into
mainfrom
clawsweeper/automerge-openclaw-openclaw-89640
Jun 3, 2026
Merged

fix(outbound): keep channel send durable when transcript mirror fails (#89626)#89812
clawsweeper[bot] merged 2 commits into
mainfrom
clawsweeper/automerge-openclaw-openclaw-89640

Conversation

@clawsweeper

@clawsweeper clawsweeper Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Makes #89640 merge-ready for the ClawSweeper automerge loop.
The edit pass should inspect the live PR diff, review comments, and failing checks; rebase if needed; keep the contributor branch credited; and stop only when validation is green or an external blocker is proven.
Known failing checks:

ClawSweeper 🐠 replacement reef notes:

  • Repair fallback: GitHub rejected the repair branch push because it updates workflow files and the ClawSweeper app token does not have workflows permission

Inherited issue-closing references from the source PR:
Fixes #89626

Co-author credit kept:

fish notes: model gpt-5.5, reasoning high; reviewed against dfe0fd7.

harjothkhara and others added 2 commits June 3, 2026 11:38
The post-delivery transcript mirror in deliverOutboundPayloads runs after the
channel payloads are already sent. Its append was unguarded, so a transient
session-lock failure ("session file changed while embedded prompt lock was
released") propagated out and the whole send was reported as failed. Callers
then retried and re-delivered the already-sent message.

For sub-agent completion announcements this produced up to 3 duplicate messages
before the announce gave up (issue #89626).

Treat the mirror as best-effort (matching the cron delivery path,
mirrorDirectDeliveryIntoTranscript): catch throws and not-ok results, log a
warning, and let the already-successful channel delivery stand. The append
still carries its idempotency key for later reconciliation.

Fixes #89626

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@clawsweeper clawsweeper Bot added size: S clawsweeper:automerge Maintainer opted this PR into bounded ClawSweeper-reviewed automerge proof: supplied External PR includes structured after-fix real behavior proof. proof: sufficient ClawSweeper judged the real behavior proof convincing. P1 High-priority user-facing bug, regression, or broken workflow. 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. clawsweeper Tracked by ClawSweeper automation labels Jun 3, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: supplied External PR includes structured after-fix real behavior proof. label Jun 3, 2026
@clawsweeper

clawsweeper Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Codex review: passed. Reviewed June 3, 2026, 9:20 AM ET / 13:20 UTC.

Summary
The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.

PR surface: Source +16, Tests +61. Total +77 across 2 files.

Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTranscript throw or return ok:false after a channel adapter send; current main has no guard at src/infra/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Review metrics: none identified.

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] End-to-end live Telegram/Raspberry Pi timing was not rerun; the available proof injects the documented mirror-lock failure at the exact post-send boundary instead.

Maintainer options:

  1. Decide the mitigation before merge
    Land the bounded outbound mirror guard after required checks so platform sends stay durable while transcript mirror misses remain warning-only diagnostics.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • No repair job is needed; review found no blocking patch defect and the automerge-labeled replacement PR can proceed through normal required checks.

Security
Cleared: No security or supply-chain concern found; the diff only changes outbound runtime error handling and regression tests.

Review details

Best possible solution:

Land the bounded outbound mirror guard after required checks so platform sends stay durable while transcript mirror misses remain warning-only diagnostics.

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

Yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTranscript throw or return ok:false after a channel adapter send; current main has no guard at src/infra/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Is this the best way to solve the issue?

Yes. Guarding the transcript mirror in the outbound substrate is the narrowest maintainable fix because the channel send has already succeeded, and the cron direct-delivery sibling already treats the same mirror append as best-effort.

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P1: The PR addresses a broken channel workflow where a successful sub-agent completion announcement can be retried and delivered multiple times.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 🚀 automerge armed: This PR is in ClawSweeper's automerge lane. Sufficient (terminal): The source PR provides after-fix terminal output for the production outbound delivery path with an injected mirror-lock failure returning one result and logging a warning instead of throwing.
  • proof: sufficient: Contributor real behavior proof is sufficient. The source PR provides after-fix terminal output for the production outbound delivery path with an injected mirror-lock failure returning one result and logging a warning instead of throwing.
Evidence reviewed

PR surface:

Source +16, Tests +61. Total +77 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 24 8 +16
Tests 1 62 1 +61
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 86 9 +77

What I checked:

  • Current main failure boundary: Current main records successful platform delivery results, then performs an unguarded transcript mirror append; if that append throws, the overall delivery promise can still reject after the channel send has already succeeded. (src/infra/outbound/deliver.ts:1954, 446a2b24c359)
  • PR implementation: The PR head wraps the post-delivery mirror append in try/catch and logs both ok:false and thrown failures while preserving the already-successful delivery result. (src/infra/outbound/deliver.ts:1970, dfe0fd711979)
  • Regression coverage: The PR adds focused tests for a thrown mirror append and an ok:false mirror result, each asserting the channel adapter is called once and the delivery returns a result. (src/infra/outbound/deliver.test.ts:3076, dfe0fd711979)
  • Caller retry path: Sub-agent completion direct delivery catches sendMessage exceptions as direct delivery failures, so an unguarded post-send mirror exception can be surfaced to the announce retry layer described by the linked issue. (src/agents/subagent-announce-delivery.ts:927, 446a2b24c359)
  • Sibling behavior: Cron direct delivery already treats transcript mirror append failures as non-fatal by catching thrown failures and logging ok:false results, which supports the PR's best-effort mirror semantics. (src/cron/isolated-agent/delivery-dispatch.ts:657, 446a2b24c359)
  • Transcript append contract: appendAssistantMessageToSessionTranscript returns an explicit ok:false shape for expected append misses and can still throw from underlying transcript operations, so best-effort callers need to handle both outcomes. (src/config/sessions/transcript.ts:43, 446a2b24c359)

Likely related people:

  • obviyus: The current shallow checkout blames the unguarded mirror append block and the sub-agent direct-delivery caller path to a current-main refactor commit authored as Ayaan Zaidi and mapped by GitHub to @obviyus. (role: recent area contributor; confidence: medium; commits: 1bd1483b62aa; files: src/infra/outbound/deliver.ts, src/agents/subagent-announce-delivery.ts)
  • joshavant: Recent GitHub path history shows sub-agent DM completion delivery work on the same announcement-delivery surface that calls outbound delivery for completion announcements. (role: adjacent owner; confidence: medium; commits: 5d3a6909fb20, b3b962a05152; files: src/agents/subagent-announce-delivery.ts)
  • steipete: Recent path history shows repeated delivery, cron, and lint/refactor touches around the sibling outbound and cron delivery surfaces used to judge the best-effort mirror invariant. (role: recent adjacent contributor; confidence: medium; commits: 1e7510ae103e, deb7bc653935; files: src/infra/outbound/deliver.ts, src/cron/isolated-agent/delivery-dispatch.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 status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane. and removed status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jun 3, 2026
@clawsweeper

clawsweeper Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

🦞✅
ClawSweeper merged this PR after the passing review.

Source: clawsweeper[bot]
Feedback: structured ClawSweeper verdict: pass (sha=dfe0fd7119791c34bef9af8f37a20254ae5937c6)
Merge status: merged by ClawSweeper automerge
Merged at: 2026-06-03T13:20:53Z
Merge commit: 79896a24d9bb

What merged:

  • The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
  • PR surface: Source +16, Tests +61. Total +77 across 2 files.
  • Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:

  • PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

The automerge loop is complete.

Automerge progress:

  • 2026-06-03 13:20:34 UTC review passed dfe0fd711979 (structured ClawSweeper verdict: pass (sha=dfe0fd7119791c34bef9af8f37a20254ae593...)
  • 2026-06-03 11:56:47 UTC merge check queued dfe0fd711979 (checks and exact-head review are ready)
  • 2026-06-03 13:04:30 UTC review queued dfe0fd711979 (queued)
  • 2026-06-03 13:14:49 UTC review queued dfe0fd711979 (after no-op repair)
  • 2026-06-03 13:20:59 UTC merged dfe0fd711979 (merged by ClawSweeper automerge)

@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jun 3, 2026
@clawsweeper
clawsweeper Bot merged commit 79896a2 into main Jun 3, 2026
236 of 252 checks passed
@clawsweeper
clawsweeper Bot deleted the clawsweeper/automerge-openclaw-openclaw-89640 branch June 3, 2026 13:20
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 4, 2026
…openclaw#89626) (openclaw#89812)

Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

Validation:
- ClawSweeper review passed for head dfe0fd7.
- Required merge gates passed before the squash merge.

Prepared head SHA: dfe0fd7
Review: openclaw#89812 (comment)

Co-authored-by: harjoth <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <[email protected]>
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request Jun 4, 2026
…openclaw#89626) (openclaw#89812)

Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

Validation:
- ClawSweeper review passed for head dfe0fd7.
- Required merge gates passed before the squash merge.

Prepared head SHA: dfe0fd7
Review: openclaw#89812 (comment)

Co-authored-by: harjoth <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <[email protected]>
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request Jun 4, 2026
…openclaw#89626) (openclaw#89812)

Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

Validation:
- ClawSweeper review passed for head dfe0fd7.
- Required merge gates passed before the squash merge.

Prepared head SHA: dfe0fd7
Review: openclaw#89812 (comment)

Co-authored-by: harjoth <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <[email protected]>
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request Jun 4, 2026
…openclaw#89626) (openclaw#89812)

Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

Validation:
- ClawSweeper review passed for head dfe0fd7.
- Required merge gates passed before the squash merge.

Prepared head SHA: dfe0fd7
Review: openclaw#89812 (comment)

Co-authored-by: harjoth <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <[email protected]>
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request Jun 4, 2026
…openclaw#89626) (openclaw#89812)

Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

Validation:
- ClawSweeper review passed for head dfe0fd7.
- Required merge gates passed before the squash merge.

Prepared head SHA: dfe0fd7
Review: openclaw#89812 (comment)

Co-authored-by: harjoth <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <[email protected]>
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request Jun 4, 2026
…openclaw#89626) (openclaw#89812)

Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

Validation:
- ClawSweeper review passed for head dfe0fd7.
- Required merge gates passed before the squash merge.

Prepared head SHA: dfe0fd7
Review: openclaw#89812 (comment)

Co-authored-by: harjoth <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <[email protected]>
849261680 pushed a commit to 849261680/openclaw that referenced this pull request Jun 7, 2026
…openclaw#89626) (openclaw#89812)

Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

Validation:
- ClawSweeper review passed for head dfe0fd7.
- Required merge gates passed before the squash merge.

Prepared head SHA: dfe0fd7
Review: openclaw#89812 (comment)

Co-authored-by: harjoth <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <[email protected]>
wangmiao0668000666 pushed a commit to wangmiao0668000666/openclaw that referenced this pull request Jun 9, 2026
…openclaw#89626) (openclaw#89812)

Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

Validation:
- ClawSweeper review passed for head dfe0fd7.
- Required merge gates passed before the squash merge.

Prepared head SHA: dfe0fd7
Review: openclaw#89812 (comment)

Co-authored-by: harjoth <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <[email protected]>
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
…openclaw#89626) (openclaw#89812)

Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

Validation:
- ClawSweeper review passed for head dfe0fd7.
- Required merge gates passed before the squash merge.

Prepared head SHA: dfe0fd7
Review: openclaw#89812 (comment)

Co-authored-by: harjoth <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <[email protected]>
vincentkoc pushed a commit to fsdwen/openclaw that referenced this pull request Jun 18, 2026
…e failure

The "session file changed while embedded prompt lock was released" error
is a concurrent-session race: the parent transcript is being modified by
turn-maintenance while the subagent completion tries to inject. Retrying
does not help because each retry independently triggers a duplicate
outbound send (3x duplicate Telegram messages reported in openclaw#91527).

Add the error message pattern to PERMANENT_ANNOUNCE_DELIVERY_ERROR_PATTERNS
so it stops triggering retries, mirroring the approach used in PR openclaw#89812
for the general outbound delivery path.

Fixes openclaw#91527

Co-Authored-By: Claude Fable 5 <[email protected]>
obviyus pushed a commit to rosenlo/openclaw that referenced this pull request Jun 25, 2026
… failure with send evidence

When a required-mode batch send fails mid-batch after an earlier payload
already succeeded, the wrapper catch in deliverOutboundPayloadsWithQueueCleanup
called failDelivery. failDelivery only bumps retryCount/lastError; it does
not advance recoveryState, so the entry stayed in send_attempt_started (set
earlier by markDeliveryPlatformSendAttemptStarted via onPlatformSendStart).

On the next Telegram reconnect, drainQueuedEntry sees send_attempt_started
and calls reconcileUnknownQueuedDelivery. When adapter reconciliation
misreports not_sent (the message was actually sent, per the outbound send
ok / messageId evidence), the entry is replayed and the user receives a
duplicate.

Fix: when the error carries send evidence (OutboundDeliveryError with
sentBeforeError === true and platformSendStarted === true), call
markQueuedPlatformOutcomeUnknown instead of failDelivery. This advances the
entry to unknown_after_send, which drain already routes through
reconcileUnknownQueuedDelivery, preserving the entry for adapter
reconciliation rather than leaving it in send_attempt_started for replay.

When there is no send evidence (sentBeforeError === false), failDelivery
remains correct: nothing reached the channel, so retrying is safe.

This is a third duplicate path distinct from openclaw#89812 (mirror best-effort)
and openclaw#92274 (subagent-announce-delivery retry); it is the outbound/deliver
wrapper catch, which neither prior fix covers.

Tests:
- regression: two payloads, first succeeds, second throws; asserts
  markDeliveryPlatformOutcomeUnknown called, failDelivery/ackDelivery not.
- guard: no send evidence; failDelivery still called.
obviyus pushed a commit that referenced this pull request Jun 25, 2026
… failure with send evidence

When a required-mode batch send fails mid-batch after an earlier payload
already succeeded, the wrapper catch in deliverOutboundPayloadsWithQueueCleanup
called failDelivery. failDelivery only bumps retryCount/lastError; it does
not advance recoveryState, so the entry stayed in send_attempt_started (set
earlier by markDeliveryPlatformSendAttemptStarted via onPlatformSendStart).

On the next Telegram reconnect, drainQueuedEntry sees send_attempt_started
and calls reconcileUnknownQueuedDelivery. When adapter reconciliation
misreports not_sent (the message was actually sent, per the outbound send
ok / messageId evidence), the entry is replayed and the user receives a
duplicate.

Fix: when the error carries send evidence (OutboundDeliveryError with
sentBeforeError === true and platformSendStarted === true), call
markQueuedPlatformOutcomeUnknown instead of failDelivery. This advances the
entry to unknown_after_send, which drain already routes through
reconcileUnknownQueuedDelivery, preserving the entry for adapter
reconciliation rather than leaving it in send_attempt_started for replay.

When there is no send evidence (sentBeforeError === false), failDelivery
remains correct: nothing reached the channel, so retrying is safe.

This is a third duplicate path distinct from #89812 (mirror best-effort)
and #92274 (subagent-announce-delivery retry); it is the outbound/deliver
wrapper catch, which neither prior fix covers.

Tests:
- regression: two payloads, first succeeds, second throws; asserts
  markDeliveryPlatformOutcomeUnknown called, failDelivery/ackDelivery not.
- guard: no send evidence; failDelivery still called.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 26, 2026
… failure with send evidence

When a required-mode batch send fails mid-batch after an earlier payload
already succeeded, the wrapper catch in deliverOutboundPayloadsWithQueueCleanup
called failDelivery. failDelivery only bumps retryCount/lastError; it does
not advance recoveryState, so the entry stayed in send_attempt_started (set
earlier by markDeliveryPlatformSendAttemptStarted via onPlatformSendStart).

On the next Telegram reconnect, drainQueuedEntry sees send_attempt_started
and calls reconcileUnknownQueuedDelivery. When adapter reconciliation
misreports not_sent (the message was actually sent, per the outbound send
ok / messageId evidence), the entry is replayed and the user receives a
duplicate.

Fix: when the error carries send evidence (OutboundDeliveryError with
sentBeforeError === true and platformSendStarted === true), call
markQueuedPlatformOutcomeUnknown instead of failDelivery. This advances the
entry to unknown_after_send, which drain already routes through
reconcileUnknownQueuedDelivery, preserving the entry for adapter
reconciliation rather than leaving it in send_attempt_started for replay.

When there is no send evidence (sentBeforeError === false), failDelivery
remains correct: nothing reached the channel, so retrying is safe.

This is a third duplicate path distinct from openclaw#89812 (mirror best-effort)
and openclaw#92274 (subagent-announce-delivery retry); it is the outbound/deliver
wrapper catch, which neither prior fix covers.

Tests:
- regression: two payloads, first succeeds, second throws; asserts
  markDeliveryPlatformOutcomeUnknown called, failDelivery/ackDelivery not.
- guard: no send evidence; failDelivery still called.
QiuYuang pushed a commit to QiuYuang/openclaw that referenced this pull request Jul 1, 2026
… failure with send evidence

When a required-mode batch send fails mid-batch after an earlier payload
already succeeded, the wrapper catch in deliverOutboundPayloadsWithQueueCleanup
called failDelivery. failDelivery only bumps retryCount/lastError; it does
not advance recoveryState, so the entry stayed in send_attempt_started (set
earlier by markDeliveryPlatformSendAttemptStarted via onPlatformSendStart).

On the next Telegram reconnect, drainQueuedEntry sees send_attempt_started
and calls reconcileUnknownQueuedDelivery. When adapter reconciliation
misreports not_sent (the message was actually sent, per the outbound send
ok / messageId evidence), the entry is replayed and the user receives a
duplicate.

Fix: when the error carries send evidence (OutboundDeliveryError with
sentBeforeError === true and platformSendStarted === true), call
markQueuedPlatformOutcomeUnknown instead of failDelivery. This advances the
entry to unknown_after_send, which drain already routes through
reconcileUnknownQueuedDelivery, preserving the entry for adapter
reconciliation rather than leaving it in send_attempt_started for replay.

When there is no send evidence (sentBeforeError === false), failDelivery
remains correct: nothing reached the channel, so retrying is safe.

This is a third duplicate path distinct from openclaw#89812 (mirror best-effort)
and openclaw#92274 (subagent-announce-delivery retry); it is the outbound/deliver
wrapper catch, which neither prior fix covers.

Tests:
- regression: two payloads, first succeeds, second throws; asserts
  markDeliveryPlatformOutcomeUnknown called, failDelivery/ackDelivery not.
- guard: no send evidence; failDelivery still called.
obviyus pushed a commit to fsdwen/openclaw that referenced this pull request Jul 1, 2026
…e failure

The "session file changed while embedded prompt lock was released" error
is a concurrent-session race: the parent transcript is being modified by
turn-maintenance while the subagent completion tries to inject. Retrying
does not help because each retry independently triggers a duplicate
outbound send (3x duplicate Telegram messages reported in openclaw#91527).

Add the error message pattern to PERMANENT_ANNOUNCE_DELIVERY_ERROR_PATTERNS
so it stops triggering retries, mirroring the approach used in PR openclaw#89812
for the general outbound delivery path.

Fixes openclaw#91527

Co-Authored-By: Claude Fable 5 <[email protected]>
badgerbees pushed a commit to badgerbees/openclaw that referenced this pull request Jul 8, 2026
…openclaw#89626) (openclaw#89812)

Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

Validation:
- ClawSweeper review passed for head dfe0fd7.
- Required merge gates passed before the squash merge.

Prepared head SHA: dfe0fd7
Review: openclaw#89812 (comment)

Co-authored-by: harjoth <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <[email protected]>
wheakerd pushed a commit to wheakerd/clawdbot that referenced this pull request Jul 15, 2026
… failure with send evidence

When a required-mode batch send fails mid-batch after an earlier payload
already succeeded, the wrapper catch in deliverOutboundPayloadsWithQueueCleanup
called failDelivery. failDelivery only bumps retryCount/lastError; it does
not advance recoveryState, so the entry stayed in send_attempt_started (set
earlier by markDeliveryPlatformSendAttemptStarted via onPlatformSendStart).

On the next Telegram reconnect, drainQueuedEntry sees send_attempt_started
and calls reconcileUnknownQueuedDelivery. When adapter reconciliation
misreports not_sent (the message was actually sent, per the outbound send
ok / messageId evidence), the entry is replayed and the user receives a
duplicate.

Fix: when the error carries send evidence (OutboundDeliveryError with
sentBeforeError === true and platformSendStarted === true), call
markQueuedPlatformOutcomeUnknown instead of failDelivery. This advances the
entry to unknown_after_send, which drain already routes through
reconcileUnknownQueuedDelivery, preserving the entry for adapter
reconciliation rather than leaving it in send_attempt_started for replay.

When there is no send evidence (sentBeforeError === false), failDelivery
remains correct: nothing reached the channel, so retrying is safe.

This is a third duplicate path distinct from openclaw#89812 (mirror best-effort)
and openclaw#92274 (subagent-announce-delivery retry); it is the outbound/deliver
wrapper catch, which neither prior fix covers.

Tests:
- regression: two payloads, first succeeds, second throws; asserts
  markDeliveryPlatformOutcomeUnknown called, failDelivery/ackDelivery not.
- guard: no send evidence; failDelivery still called.

(cherry picked from commit 71422a9)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clawsweeper:automerge Maintainer opted this PR into bounded ClawSweeper-reviewed automerge clawsweeper Tracked by ClawSweeper automation P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: S status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sub-agent completion events delivered 3x — duplicate messages on auto-announce retry

1 participant