fix(slack): stop a progress card whose message will not accept edits - #747
Merged
Conversation
added 2 commits
September 11, 2026 22:00
A Slack stream expires while a long job keeps working. The card then falls back to editing the message the stream owned, which is what keeps a long run visible. Nothing handled the case where that message is also gone: chat.update returned message_not_found, the idle loop re-dirtied the snapshot 3.2 seconds later, and the same doomed request went out 47 consecutive times over two and a half minutes with no bound but the end of the job (#744). message_not_found and cant_update_message now end the live loop immediately - the message is unreachable and no retry changes that - and three consecutive failures of any other kind end it too, since a transport that has rejected the same request three times running will not take the fourth. Rate limits are excluded: the embargo already spaces those and the content is retried. Successful fallback edits are untouched, so an expired stream still keeps its card current through a long job. Finalizing a card known to be gone spends no request proving it again. A dead card is never replaced by a second one. Refs #744
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Base automatically changed from
codex/slack-request-scoped-destination
to
dev
September 11, 2026 13:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #746.
A Slack stream expires after about five minutes. A long job keeps working, so the progress card falls back to editing the message the stream owned — that part is deliberate and stays. What was missing is the case where that message is also gone.
In the 2026-09-11 incident the fallback
chat.updatereturnedmessage_not_found, nothing promoted that to a stop, and the idle loop re-dirtied the snapshot 3.2 seconds later. The same doomed request went out 47 consecutive times across two and a half minutes, with no bound except the end of the job (serve.log19570–19662).What this does
endLive(reason, gone)ends the live loop once, clears both timers, and countsslack.progress.stream_state_lost.message_not_foundandcant_update_messageend it immediately. The message is unreachable; no retry changes that, and finalizing a card known to be gone spends no request proving it again.startIdle's callback re-checks the flag, which could previously be raised while its timer was already pending.A dead card is never replaced by a second one, and the card freezes at its last known state rather than disappearing.
What this deliberately does not do
Cap successful fallback edits. An earlier draft allowed one catch-up edit after expiry and then froze, which is what the issue suggested — but that undoes
35e3a994, where an expired stream keeps its card current through a long run. The storm came from repeated failures, not repeated successes, so the bound belongs on failures.a stream closed after five minutes continues editing its own status through a long jobandretains live status through minute nineteenboth still pass unmodified.This also does not stop the misroute. The card's clock is stamped once at handle creation (
progress-activity.ts:122) and never reset, so "경과 531초" in a two-second-old thread was an existing handle seen at a new address — a destination-binding question (#746), not a lifetime one.Testing
tests/unit/slack-progress-stream.test.ts+slack-progress-lifecycle+slack-progress-observer: 110/110, no existing case modified. Two new: SPS-744 for the gone-message path (one edit discovers it, five more minutes add nothing, nopostMessage, no timers left) and SPS-744 for the consecutive-failure bound.npm run gate:all— 23/23.Refs #744