Skip to content

Discord: reaction events missing thread context #127

@ghardin1314

Description

@ghardin1314

Bug Description

handleGatewayReaction and handleForwardedReaction in the Discord adapter produce channel-level thread IDs for reactions on messages inside threads. The threadId on ReactionEvent is a 3-segment ID (discord:{guildId}:{channelId}) even when the reacted message is in a thread, where it should be 4-segment (discord:{guildId}:{parentChannelId}:{threadId}).

Steps to Reproduce

  1. Register a reaction handler: chat.onReaction(["x"], (event) => { console.log(event.threadId); })
  2. Send a message that triggers the bot to reply in a Discord thread
  3. React with ❌ on a message inside that thread
  4. Observe event.threadId — it's discord:{guildId}:{threadChannelId} (3 segments) instead of discord:{guildId}:{parentChannelId}:{threadChannelId} (4 segments)

Expected Behavior

event.threadId should be the full 4-segment ID (discord:{guildId}:{parentChannelId}:{threadId}) when the reaction is on a message inside a thread, matching the format produced by handleGatewayMessage.

Actual Behavior

event.threadId is a 3-segment channel-level ID (discord:{guildId}:{channelId}) — the thread snowflake is placed in the channel slot and the parent channel is lost. This means event.threadId from onReaction doesn't match the threadId used by onNewMention/onSubscribedMessage for the same thread.

Code Sample

// handleGatewayReaction currently (packages/adapter-discord/src/index.ts ~L1664):
const threadId = this.encodeThreadId({ guildId, channelId, threadId: undefined });

// Should resolve thread context like handleGatewayMessage does (~L1555):
const isInThread = reaction.message.channel?.isThread?.();
let parentChannelId = channelId;
let discordThreadId;
if (isInThread && "parentId" in reaction.message.channel && reaction.message.channel.parentId) {
  discordThreadId = channelId;
  parentChannelId = reaction.message.channel.parentId;
}
const threadId = this.encodeThreadId({ guildId, channelId: parentChannelId, threadId: discordThreadId });

Chat SDK Version

4.15.0

Node.js Version

No response

Platform Adapter

Discord

Operating System

macOS

Additional Context

Both handleGatewayReaction (~L1664) and handleForwardedReaction (~L547) are affected. The fix pattern already

Note: handleGatewayReaction's type signature narrows reaction.message to { id: string; channelId: string; guildId: string | null }, which doesn't include channel. But at runtime, the caller passes the full discord.js MessageReaction object, so reaction.message.channel (with .isThread() and .parentId) is available. The type signature needs to be widened to include channel for the fix to typecheck.exists in handleGatewayMessage (~L1555) which uses message.channel.isThread() and channel.parentId to resolve the correct thread context.

I (claude) patched this locally and it worked as expected

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions