Skip to content

ackReactionScope: "all" is silently overridden by isRoomEvent gate #87368

Description

@paul-phan

Summary

channels.<provider>.ackReactionScope: "all" does not actually ack all inbound messages. A hardcoded !isRoomEvent gate in message-handler.process suppresses ack reactions for any inbound classified as room_event, even though the scope explicitly says "all".

This contradicts the schema description for ackReactionScope, which advertises "all" as unconditional.

Version

OpenClaw 2026.5.26 (10ad3aa)

Repro

  1. Set Discord ack reaction config:
    "channels": {
      "discord": {
        "ackReaction": "",
        "accounts": { "samantha": { "ackReaction": "" } }
      }
    },
    "messages": {
      "ackReactionScope": "all",
      "groupChat": { "unmentionedInbound": "room_event" }
    }
  2. Restart gateway, confirm config applied via openclaw config get.
  3. Post a message in a guild thread/subthread where the bot is already participating, without @-mentioning the bot.
  4. Bot responds normally (autoThread context keeps the conversation alive).
  5. Expected: ack reaction () appears on the user's message.
  6. Actual: no reaction. messages.reactions is [] for the user message.

Manual reactions via message(action=reactionAdd) work fine — the issue is specifically the auto-ack code path.

Root cause

dist/message-handler.process-LhrhAUW3.js:904-905:

const isRoomEvent = ctx.inboundEventKind === "room_event";
const shouldAckReaction$1 = () => Boolean(!isRoomEvent && ackReaction && shouldAckReaction({
  scope: ackReactionScope,
  isDirect: isDirectMessage,
  ...
}));

The !isRoomEvent short-circuit runs before shouldAckReaction(...), so scope: "all" never gets a chance to override it. The shouldAckReaction helper in ack-reactions.ts correctly returns true for scope "all", but the outer expression masks that.

Because messages.groupChat.unmentionedInbound: "room_event" is a legitimate, documented configuration (quiet always-on listening), inbound thread messages without an explicit @-mention are classified as room_event — and ack reactions get silently dropped.

Why it matters

  • ackReactionScope schema help text says "all" = "always send the ack reaction" — users expect literally all messages.
  • Manual reactions work, so the bot clearly has permission and the emoji is valid; the suppression is purely in the gate logic.
  • There is no unmentionedInbound override at account / guild / channel level, so users can't selectively re-enable ack in a single thread.

Proposed fix

Two viable options:

Option A (preferred) — Make scope "all" truly bypass isRoomEvent:

const isRoomEvent = ctx.inboundEventKind === "room_event";
const ackForcedAll = ackReactionScope === "all";
const shouldAckReaction$1 = () => Boolean((ackForcedAll || !isRoomEvent) && ackReaction && shouldAckReaction({ ... }));

Option B — Add an explicit override flag:

"messages": {
  "ackReactionScope": "all",
  "ackReactionOnRoomEvent": true
}

Option A is cleaner since the contradiction is already in the doc/contract of "all".

Workaround for users today

@-mention the bot in the thread → classified as user_request → ack fires.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions