-
-
Notifications
You must be signed in to change notification settings - Fork 69k
Discord Components V2: Select menus fail — wildcard registration collision in Carbon ComponentHandler #29229
Description
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 ← SKIPPEDSince 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