openclaw - 💡(How to fix) Fix [Bug]: Discord message-tool send fails with "Ambiguous Discord recipient" for bare numeric channel IDs (2026.5.22)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

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.

Error Message

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. Full error string surfaced as the message-tool toolResult.content: throw new Error(options.ambiguousMessage ?? Ambiguous Discord recipient "${trimmed}". For DMs use "user:${trimmed}" or "<@${trimmed}>"; for channels use "channel:${trimmed}".);

Root Cause

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.

Fix Action

Fix / Workaround

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.

Code Example

Ambiguous Discord recipient "<id>". For DMs use "user:<id>" or "<@<id>>"; for channels use "channel:<id>".

---

Ambiguous Discord recipient "<channelId>". For DMs use "user:<channelId>" or "<@<channelId>>"; for channels use "channel:<channelId>".

---

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);
RAW_BUFFERClick to expand / collapse

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

  1. Have an OpenClaw 2026.5.22 install with Discord configured and at least one channel/session bound to a guild text channel.
  2. 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.
  3. 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:

FileLinesCall
dist/send.outbound-Cy_i_Kpm.js50, 86parseAndResolveRecipient(to, cfg, opts.accountId) — main text send
dist/send.components-C0c1TiP_.js414, 461components send
dist/send-BASUWZZP.js727voice message send
dist/outbound-session-route-CyNVJMI-.js8, 36resolveDiscordOutboundTargetKindHint 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:

  1. Change parseAndResolveRecipient's default to parseOptions = { defaultKind: "channel" } so all current outbound callers fall back to channel-kind for bare numerics, or
  2. 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.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

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.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Bug]: Discord message-tool send fails with "Ambiguous Discord recipient" for bare numeric channel IDs (2026.5.22)