Fix Slack retry for session init conflicts#99647
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 3, 2026, 6:23 PM ET / 22:23 UTC. Summary PR surface: Source +70, Tests +139. Total +209 across 2 files. Reproducibility: yes. The current-main handler path can be reproduced in the Slack message-handler harness by rejecting dispatch with a wrapped Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the focused Slack handler fix after maintainer review, preserving native retry through delivery gates and relay retry through unacknowledged redelivery. Do we have a high-confidence way to reproduce the issue? Yes. The current-main handler path can be reproduced in the Slack message-handler harness by rejecting dispatch with a wrapped Is this the best way to solve the issue? Yes. The Slack message handler is the narrow owner boundary because it owns Slack inbound delivery persistence, seen-message release, debounce retry, and relay ack behavior; the PR avoids moving Slack-specific policy into core. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against af420dbee597. Label changesLabel justifications:
Evidence reviewedPR surface: Source +70, Tests +139. Total +209 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
|
8932462 to
b34a741
Compare
|
@clawsweeper re-review Addressed the retry-ownership finding on exact head
Proof:
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
* Fix Slack retry for session init conflicts * fix(slack): separate native and relay retries * style(slack): make completion exits explicit --------- Co-authored-by: Peter Steinberger <[email protected]>
…onflict (openclaw#100944) Port the bounded retry-with-backoff pattern from Slack (openclaw#99647) and Telegram to Signal's debounce onFlush handler. When a follow-up Signal DM arrives shortly after a reply completes, the session store may still hold a stale snapshot, causing a 'reply session initialization conflicted' error. Slack and Telegram recover by re-enqueuing the inbound message after a short delay (up to 3 attempts). Signal's onFlush now catches retryable errors, tracks attempts per debounce key, and re-enqueues entries via inboundDebouncer with a 1s delay. Non-retryable errors are still thrown to onError.
Port bounded retry-with-backoff to Signal's debounce flush path, matching the existing Slack/Telegram behavior for the same error class (openclaw#99647, openclaw#96550). - isRetryableSignalInboundError(): walks error cause chain matching "reply session initialization conflicted for ..." - flushWithRetry(): wraps handleSignalInboundMessage with up to 3 retries at 1s intervals - 6 proof tests (3 fake-timer + 3 real-environment wall-clock) - isRetryableSignalInboundError exported for external verification Fixes openclaw#100944
…onflict (openclaw#100944) Port the bounded retry-with-backoff pattern from Slack (openclaw#99647) and Telegram to Signal's debounce onFlush handler. When a follow-up Signal DM arrives shortly after a reply completes, the session store may still hold a stale snapshot, causing a 'reply session initialization conflicted' error. Slack and Telegram recover by re-enqueuing the inbound message after a short delay (up to 3 attempts). Signal's onFlush now catches retryable errors, tracks attempts per debounce key, and re-enqueues entries via inboundDebouncer with a 1s delay. Non-retryable errors are still thrown to onError.
Port bounded retry-with-backoff to Signal's debounce flush path, matching the existing Slack/Telegram behavior for the same error class (openclaw#99647, openclaw#96550). - isRetryableSignalInboundError(): walks error cause chain matching "reply session initialization conflicted for ..." - flushWithRetry(): wraps handleSignalInboundMessage with up to 3 retries at 1s intervals - 6 proof tests (3 fake-timer + 3 real-environment wall-clock) - isRetryableSignalInboundError exported for external verification Fixes openclaw#100944
Port bounded retry-with-backoff to Signal's debounce flush path, matching the existing Slack/Telegram behavior for the same error class (openclaw#99647, openclaw#96550). - isRetryableSignalInboundError(): walks error cause chain matching "reply session initialization conflicted for ..." - flushWithRetry(): wraps handleSignalInboundMessage with up to 3 retries at 1s intervals - 6 proof tests (3 fake-timer + 3 real-environment wall-clock) - isRetryableSignalInboundError exported for external verification Fixes openclaw#100944
Port bounded retry-with-backoff to Signal's debounce flush path, matching the existing Slack/Telegram behavior for the same error class (openclaw#99647, openclaw#96550). - isRetryableSignalInboundError(): walks error cause chain matching "reply session initialization conflicted for ..." - flushWithRetry(): wraps handleSignalInboundMessage with up to 3 retries at 1s intervals - 6 proof tests (3 fake-timer + 3 real-environment wall-clock) - isRetryableSignalInboundError exported for external verification Fixes openclaw#100944
Port bounded retry-with-backoff to Signal's debounce flush path, matching the existing Slack/Telegram behavior for the same error class (openclaw#99647, openclaw#96550). - isRetryableSignalInboundError(): walks error cause chain matching "reply session initialization conflicted for ..." - flushWithRetry(): wraps handleSignalInboundMessage with up to 3 retries at 1s intervals - 6 proof tests (3 fake-timer + 3 real-environment wall-clock) - isRetryableSignalInboundError exported for external verification Fixes openclaw#100944
…ct (openclaw#108320) When reply dispatch fails with 'reply session initialization conflicted', the Feishu channel now retries with exponential backoff (250ms to 2s, up to 4 retries) instead of silently dropping the inbound message. Matches the retry pattern already used by Slack (openclaw#99647) and Signal (openclaw#100944, openclaw#103218). - Fixes off-by-one in retry/attempt counting: first attempt is outside the retry loop, and MAX_RETRIES = 4 consistently with the delay array - Fixes eslint no-promise-executor-return lint error at bot.ts:121 - Adds 6 focused unit tests covering schedule, exhaustion, and shutdown - Exports runFeishuDispatchWithSessionInitRetry for testing
Summary:
Slack dispatch failed->reply session initialization conflicted ...case.Tests:
/home/dev-user/.local/share/crabbox-openai/openclaw/releases/fbfadbd806e16932f2c6bcaf4f283dbb1fc536f8/node_modules/.bin/oxfmt --check --threads=1 extensions/slack/src/monitor/message-handler.ts extensions/slack/src/monitor/message-handler.test.tsnode scripts/run-vitest.mjs run extensions/slack/src/monitor/message-handler.app-mention-race.test.ts extensions/slack/src/monitor/message-handler.test.tsnode scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.extensions.json extensions/slack/src/monitor/message-handler.ts extensions/slack/src/monitor/message-handler.test.tsNote: the fresh PR worktree could not run
pnpm installdirectly because the internal registry returned 403 for@openclaw/crabline; tests and lint were run using the already-installed repo dependency set from the release checkout.