Skip to content

Discord Components V2: Select menus fail — wildcard registration collision in Carbon ComponentHandler #29229

@Tranman324

Description

@Tranman324

Bug Report — OpenClaw 2026.2.15+

Environment

  • OS: Ubuntu 22.04 (x64)
  • Node: v24.13.1
  • OpenClaw: 2026.2.26
  • @buape/carbon: (bundled with OpenClaw)

Problem

Discord select menus (string, user, role, channel, mentionable) sent via the message tool with components parameter fail on interaction. Buttons work correctly. Users see Discord's "This interaction failed" error when clicking any select menu.

Root Cause

In @buape/carbon/dist/src/internals/ComponentHandler.js, registerComponent() deduplicates by customId alone:

registerComponent(component) {
    if (!this.componentCache.has(component.customId)) {
        this.componentCache.set(component.customId, component);
    }
}

OpenClaw registers multiple wildcard component handlers that all use customId = "*":

components.push(createDiscordComponentButton(componentContext));        // customId: "*", type: 2
components.push(createDiscordComponentStringSelect(componentContext));  // customId: "*", type: 3 ← SKIPPED
components.push(createDiscordComponentUserSelect(componentContext));    // customId: "*", type: 5 ← SKIPPED
components.push(createDiscordComponentRoleSelect(componentContext));    // customId: "*", type: 6 ← SKIPPED

Since DiscordComponentButton (type 2) is registered first with customId = "*", the has() check returns true for all subsequent wildcard components, silently dropping them.

When findComponent() runs its wildcard fallback pass, it finds the Button (type 2) but rejects it because component.type !== componentType (3 for select). Returns undefined → throws "Unknown component" error.

Error from gateway logs

[EventQueue] Listener InteractionEventListener failed for event INTERACTION_CREATE: 
Error: Unknown component with type 3 and custom ID occomp:cid=sel_S_oAwNge was received, 
did you forget to register the component?
    at ComponentHandler.handleInteraction

Suggested Fix

Key the component cache by composite customId:type instead of customId alone:

registerComponent(component) {
    const cacheKey = \`${component.customId}:${component.type}\`;
    if (!this.componentCache.has(cacheKey)) {
        this.componentCache.set(cacheKey, component);
    }
}

This allows multiple wildcard component types to coexist. No changes needed to findComponent() since it iterates .values().

Current Workaround

We patch ComponentHandler.js locally after each install/update. Works but needs reapplying after every openclaw update.

Affects

  • Discord select menus (all types)
  • Discord modals triggered from select menu interactions
  • Any non-button interactive component using wildcard customId registration

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions