#7758: fix: prevent opts closure reuse across messages in shared followup queue
stale
Cluster:
Slack Thread Management Improvements
When multiple messages from the same session enter a shared followup queue, the queue runner (created by createFollowupRunner) captured opts in a closure. This caused all messages in that queue to reuse the first message's opts, leading to incorrect deliver callbacks being invoked.
This fix stores opts directly in the FollowupRun object, ensuring each queued message carries its own reply options. The followup runner now prefers queued.opts over closure-captured opts, maintaining backwards compatibility while fixing the closure reuse issue.
Changes:
- Add opts field to FollowupRun type (queue/types.ts)
- Pass opts when creating followupRun (get-reply-run.ts)
- Use queued.opts ?? opts in followup runner (followup-runner.ts)
Co-Authored-By: Claude Sonnet 4.5
Related Issues:
- #4424
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR fixes a subtle followup-queue bug where `createFollowupRunner` captured `opts` in a closure, causing multiple queued messages in a shared followup queue to reuse the first message’s callbacks (e.g., delivering replies via the wrong `onBlockReply`). It does this by adding an `opts` field to `FollowupRun`, populating it when enqueuing, and preferring `queued.opts ?? opts` when dispatching followup payloads.
The change fits cleanly into the existing queue architecture: `get-reply-run.ts` constructs the `FollowupRun` object, `queue/types.ts` defines the queued payload shape, and `followup-runner.ts` is the executor that now picks per-message delivery options.
<h3>Confidence Score: 4/5</h3>
- This PR is likely safe to merge, with one remaining closure-capture inconsistency around typing heartbeat behavior.
- The change is small and targeted (adds `FollowupRun.opts` and uses it for delivery), but `typingSignals` is still initialized from closure-captured `opts?.isHeartbeat`, which can reintroduce per-message behavior drift in shared queues.
- src/auto-reply/reply/followup-runner.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#8205: fix: flush followup messages incrementally
by hanxiao · 2026-02-03
76.5%
#5080: fix(reply): fix duplicate block replies by unblocking coalesced pay...
by yassine20011 · 2026-01-31
75.2%
#19083: Slack: preserve per-thread context and consistent thread replies
by jkimbo · 2026-02-17
74.8%
#4749: fix: handle string thread IDs in queue drain for Slack
by nvonpentz · 2026-01-30
74.5%
#13881: fix: Address Greptile feedback - test isolation and channel resolution
by trevorgordon981 · 2026-02-11
74.3%
#8175: fix: suppress raw API errors for non-owners
by Rakshi2609 · 2026-02-03
73.5%
#20406: fix(slack): respect replyToMode when computing statusThreadTs in DMs
by QuinnYates · 2026-02-18
73.4%
#3335: Fixes cron jobs
by hkirat · 2026-01-28
73.0%
#22433: Slack: fix thread context loss after session reset
by stgarrity · 2026-02-21
72.7%
#7353: fix: prevent silent message drops after config.patch restart
by 18-RAJAT · 2026-02-02
72.6%