fix(slack): await draft stream flush before messageId check#23118
Open
dashed wants to merge 1 commit intoopenclaw:mainfrom
Open
fix(slack): await draft stream flush before messageId check#23118dashed wants to merge 1 commit intoopenclaw:mainfrom
dashed wants to merge 1 commit intoopenclaw:mainfrom
Conversation
This was referenced Feb 22, 2026
Contributor
Author
|
Note on Windows CI failure: The `checks-windows (node, test)` failure is a pre-existing issue on main — not caused by this PR. Fix: #23128 |
98048c8 to
630f358
Compare
a9058b6 to
215d7ed
Compare
…t duplicate messages
215d7ed to
473fc58
Compare
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.
Summary
Fixes #19373.
When Slack streaming is enabled,
sendMessageSlack()is called fire-and-forget inside the draft stream. The deliver callback indispatch.tsthen readsdraftStream.messageId()to decide whether it can finalize via preview-edit — but the send hasn't resolved yet, somessageId()returnsundefined. This causescanFinalizeViaPreviewEditto evaluatefalse, and the dispatcher falls through to normal delivery, posting a duplicate message.This PR adds
await draftStream?.flush()before themessageId()read so the in-flight send resolves first.Root Cause
In
dispatchPreparedSlackMessage(dispatch.ts), the deliver callback evaluates:But
messageId()is only populated after the draft stream'ssendMessageSlack()promise resolves. Since the send is fire-and-forget (kicked off bystream.update()), there's a race: if the deliver callback runs before the send completes,messageId()returnsundefinedand the message is delivered normally — duplicating the streamed draft.The Discord handler already does
await flushDraft()before readingmessageId(atmessage-handler.process.ts:555), but the Slack handler was missing the equivalent call.Changes
src/slack/monitor/message-handler/dispatch.ts— Add flush before messageId read:src/slack/draft-stream.test.ts— Two new tests:Comparison with #20248 and #20623
messageId()readmessageId()read)messageId()is populatedcanFinalizeViaPreviewEditrecipient_team_id)The key difference from #20248: that PR flushes before the final
deliverRepliescall, but thecanFinalizeViaPreviewEditevaluation happens before delivery. IfmessageId()is stillundefinedat evaluation time, the code has already decided to skip preview-edit and deliver normally — flushing afterward doesn't prevent the duplicate. This PR flushes before the evaluation, which is the correct fix point.Test Plan
src/slack/draft-stream.test.tsflush resolves in-flight send so messageId is available— verifies the race condition fixflush is safe to call when no draft has been started— verifies no-op safetyRelated
Greptile Summary
Adds
await draftStream?.flush()before readingmessageId()in the deliver callback to ensure in-flight draft sends complete before thecanFinalizeViaPreviewEditcheck. Without this flush, a race condition causesmessageId()to returnundefined, preventing preview-edit finalization and resulting in duplicate Slack messages.sendMessageSlack()hasn't resolved whenmessageId()is checkedmessage-handler.process.ts)Confidence Score: 5/5
Last reviewed commit: 132c809
Rebase History
eb0758e1722c(v2026.3.7)473fc58c5e96.