Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
The message tool's Discord outbound send paths throw Ambiguous Discord recipient "<id>"... for bare numeric channel IDs that worked in earlier releases. Channel sessions whose runtime supplies a bare numeric to (no channel: prefix) can no longer reply to their own channel via the message tool.
This appears closely related to the DM-side fixes in #72401 and #75359, but the regression is now on the channel side: a tightened parseDiscordTarget ambiguity check is reached because several outbound send paths drop the defaultKind: "channel" parse option that resolveDiscordTargetChannelId still passes correctly.
Steps to reproduce
- Have an OpenClaw 2026.5.22 install with Discord configured and at least one channel/session bound to a guild text channel.
- Trigger any LLM-driven
message tool send where the model emits { "action": "send", "to": "<bare numeric channel ID>", "message": "..." }. This is the natural form when the model has the channel ID in context but no channel: prefix discipline.
- Observe the tool result.
Expected behavior
Outbound text send is delivered to the channel. Historic behavior (and the explicit fast path in resolveDiscordTargetChannelId) is to interpret a bare numeric outbound target as a channel ID.
Actual behavior
Tool result is an error with body:
Ambiguous Discord recipient "<id>". For DMs use "user:<id>" or "<@<id>>"; for channels use "channel:<id>".
In session sessions that auto-relay the channel ID to the tool, this is a permafail: every reply round trips the same error and the channel never sees a response.
OpenClaw version
2026.5.22
Operating system
macOS 26.2
Install method
npm global
Model
claude-opus-4-7 (also reproducible with gpt-5.4 / Codex sessions in the same workspace)
Provider / routing chain
claude-cli (Claude Max), openai-codex/gpt-5.4 — same symptom both sides.
Additional provider/model setup details
No response
Logs, screenshots, and evidence
Full error string surfaced as the message-tool toolResult.content:
Ambiguous Discord recipient "<channelId>". For DMs use "user:<channelId>" or "<@<channelId>>"; for channels use "channel:<channelId>".
Root cause (dist code, 2026.5.22)
dist/target-parsing-D1FhMbX6.js lines 29–32 — bare numeric IDs throw unless options.defaultKind is supplied:
if (/^\d+$/.test(trimmed)) {
if (options.defaultKind) return buildMessagingTarget(options.defaultKind, trimmed, trimmed);
throw new Error(options.ambiguousMessage ?? `Ambiguous Discord recipient "${trimmed}". For DMs use "user:${trimmed}" or "<@${trimmed}>"; for channels use "channel:${trimmed}".`);
}
return buildMessagingTarget("channel", trimmed, trimmed);
Outbound send paths that call this without a defaultKind:
| File |
Lines |
Call |
dist/send.outbound-Cy_i_Kpm.js |
50, 86 |
parseAndResolveRecipient(to, cfg, opts.accountId) — main text send |
dist/send.components-C0c1TiP_.js |
414, 461 |
components send |
dist/send-BASUWZZP.js |
727 |
voice message send |
dist/outbound-session-route-CyNVJMI-.js |
8, 36 |
resolveDiscordOutboundTargetKindHint returns undefined for bare numeric input |
parseAndResolveRecipient itself signature-defaults parseOptions = {}, so callers that omit the option propagate the empty options all the way to parseDiscordTarget, which then throws.
For contrast, dist/send.shared-DBAwZLzi.js line 650 (resolveDiscordTargetChannelId) is correct — it passes { defaultKind: "channel" } explicitly.
Proposed fix
Either:
- Change
parseAndResolveRecipient's default to parseOptions = { defaultKind: "channel" } so all current outbound callers fall back to channel-kind for bare numerics, or
- Update each outbound send call site (
send.outbound, send.components ×2, voice send, and outbound-session-route) to pass { defaultKind: "channel" } explicitly, matching resolveDiscordTargetChannelId.
Option 1 is a one-line restoration of pre-2026.5.20 behavior. The DM-prefix discipline from #72401 / #75359 is preserved because user: / <@id> / discord:user: prefixes still resolve to kind=user regardless of defaultKind.
Impact and severity
- Severity: High. Discord channel sessions cannot reply to their own channel via the message tool when the model emits a bare numeric
to.
- Frequency: Every reply round trip on affected sessions.
- Consequence: Discord channels appear silent. Sessions may also stall on
isError: true results and burn tokens retrying.
Additional information
Not mentioned in 2026.5.20 or 2026.5.22 release notes. Likely introduced alongside the 2026.5.20 "Agents/message-tool: normalize non-canonical message body aliases" (#84079) and 2026.5.22 "Channels/message tool: resolve configured external channel plugins during in-agent channel selection" (#85022) refactors, both of which touch the same call paths.
Local workaround attempted: none in the affected sessions, since the bare numeric to comes from how the message tool is currently being invoked by the model.
Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
The
messagetool's Discord outbound send paths throwAmbiguous Discord recipient "<id>"...for bare numeric channel IDs that worked in earlier releases. Channel sessions whose runtime supplies a bare numericto(nochannel:prefix) can no longer reply to their own channel via the message tool.This appears closely related to the DM-side fixes in #72401 and #75359, but the regression is now on the channel side: a tightened
parseDiscordTargetambiguity check is reached because several outbound send paths drop thedefaultKind: "channel"parse option thatresolveDiscordTargetChannelIdstill passes correctly.Steps to reproduce
messagetool send where the model emits{ "action": "send", "to": "<bare numeric channel ID>", "message": "..." }. This is the natural form when the model has the channel ID in context but nochannel:prefix discipline.Expected behavior
Outbound text send is delivered to the channel. Historic behavior (and the explicit fast path in
resolveDiscordTargetChannelId) is to interpret a bare numeric outbound target as a channel ID.Actual behavior
Tool result is an error with body:
In session sessions that auto-relay the channel ID to the tool, this is a permafail: every reply round trips the same error and the channel never sees a response.
OpenClaw version
2026.5.22
Operating system
macOS 26.2
Install method
npm global
Model
claude-opus-4-7 (also reproducible with gpt-5.4 / Codex sessions in the same workspace)
Provider / routing chain
claude-cli (Claude Max), openai-codex/gpt-5.4 — same symptom both sides.
Additional provider/model setup details
No response
Logs, screenshots, and evidence
Full error string surfaced as the message-tool
toolResult.content:Root cause (dist code, 2026.5.22)
dist/target-parsing-D1FhMbX6.jslines 29–32 — bare numeric IDs throw unlessoptions.defaultKindis supplied:Outbound send paths that call this without a
defaultKind:dist/send.outbound-Cy_i_Kpm.jsparseAndResolveRecipient(to, cfg, opts.accountId)— main text senddist/send.components-C0c1TiP_.jsdist/send-BASUWZZP.jsdist/outbound-session-route-CyNVJMI-.jsresolveDiscordOutboundTargetKindHintreturnsundefinedfor bare numeric inputparseAndResolveRecipientitself signature-defaultsparseOptions = {}, so callers that omit the option propagate the empty options all the way toparseDiscordTarget, which then throws.For contrast,
dist/send.shared-DBAwZLzi.jsline 650 (resolveDiscordTargetChannelId) is correct — it passes{ defaultKind: "channel" }explicitly.Proposed fix
Either:
parseAndResolveRecipient's default toparseOptions = { defaultKind: "channel" }so all current outbound callers fall back to channel-kind for bare numerics, orsend.outbound,send.components×2, voicesend, andoutbound-session-route) to pass{ defaultKind: "channel" }explicitly, matchingresolveDiscordTargetChannelId.Option 1 is a one-line restoration of pre-2026.5.20 behavior. The DM-prefix discipline from #72401 / #75359 is preserved because
user:/<@id>/discord:user:prefixes still resolve tokind=userregardless ofdefaultKind.Impact and severity
to.isError: trueresults and burn tokens retrying.Additional information
Not mentioned in 2026.5.20 or 2026.5.22 release notes. Likely introduced alongside the 2026.5.20 "Agents/message-tool: normalize non-canonical message body aliases" (#84079) and 2026.5.22 "Channels/message tool: resolve configured external channel plugins during in-agent channel selection" (#85022) refactors, both of which touch the same call paths.
Local workaround attempted: none in the affected sessions, since the bare numeric
tocomes from how the message tool is currently being invoked by the model.