Skip to content

fix(discord): parse provider-prefixed channel targets#78625

Merged
Patrick-Erichsen merged 2 commits intomainfrom
pe/discord-provider-prefixed-channel-target
May 6, 2026
Merged

fix(discord): parse provider-prefixed channel targets#78625
Patrick-Erichsen merged 2 commits intomainfrom
pe/discord-provider-prefixed-channel-target

Conversation

@Patrick-Erichsen
Copy link
Copy Markdown
Contributor

@Patrick-Erichsen Patrick-Erichsen commented May 6, 2026

Summary

  • Fixes [Bug]: message tool action=send to Discord fails with "Unknown Channel" despite bot being connected #78572 by resolving bare numeric Discord message-tool targets through Discord's allowFrom-aware target resolver, so allowlisted DM user IDs route as user:<id> instead of being treated as channels.
  • Parse Discord provider-prefixed channel/user targets before the legacy discord:<id> DM shorthand, so discord:channel:<id> remains a channel target.
  • Preserve legacy discord:<userId> direct-message routing.
  • Add Discord-owned parser, normalizer, outbound route, outbound adapter, and plugin resolver coverage.

Fixes #78572.

Real behavior proof

Behavior addressed: Discord message(action="send") target resolution for the #78572 repro shape: a bare numeric Discord user ID that appears in channels.discord.allowFrom must route as user:<id> for DM delivery, not as channel:<id>. Also verifies provider-prefixed discord:channel:<id> routes as a channel target and can deliver a real Discord channel message.

Real environment tested: Local OpenClaw CLI built from this PR branch on macOS, using a temporary OPENCLAW_HOME/XDG_CONFIG_HOME and a temp Discord config with the local Discord bot token provided through DISCORD_BOT_TOKEN. The live channel delivery target was Discord channel 1501672157829140502.

Exact steps or command run after the patch:

  1. Create a temp OpenClaw home and patch config with channels.discord.enabled=true, channels.discord.token={ source: "env", provider: "default", id: "DISCORD_BOT_TOKEN" }, and channels.discord.allowFrom=["*"].
  2. Run pnpm openclaw message send --channel discord --target "discord:channel:1501672157829140502" --message "OpenClaw live Discord delivery check for PR 78625 2026-05-06T21:25:34Z" --json.
  3. Separately run the [Bug]: message tool action=send to Discord fails with "Unknown Channel" despite bot being connected #78572 target-resolution dry-run with channels.discord.allowFrom=["1439091261670948987"]: pnpm openclaw message send --channel discord --target "1439091261670948987" --message "dry-run allowFrom DM target check" --dry-run --json.

Evidence after fix:
Live Discord channel delivery returned:

{
  "action": "send",
  "channel": "discord",
  "dryRun": false,
  "handledBy": "core",
  "payload": {
    "channel": "discord",
    "to": "channel:1501672157829140502",
    "via": "direct",
    "result": {
      "messageId": "1501696468438880377",
      "channel": "discord",
      "receipt": {
        "primaryPlatformMessageId": "1501696468438880377",
        "parts": [
          {
            "platformMessageId": "1501696468438880377",
            "kind": "text",
            "raw": {
              "channel": "discord",
              "messageId": "1501696468438880377",
              "channelId": "1501672157829140502"
            }
          }
        ]
      }
    }
  }
}

The #78572 bare numeric allowlisted DM dry-run returned:

{
  "action": "send",
  "channel": "discord",
  "dryRun": true,
  "handledBy": "core",
  "payload": {
    "channel": "discord",
    "to": "user:1439091261670948987",
    "via": "direct",
    "mediaUrl": null,
    "dryRun": true
  }
}

Observed result after fix: The provider-prefixed Discord channel target delivered a real Discord message with platform message id 1501696468438880377, and the #78572 bare numeric allowlisted Discord target resolves to user:1439091261670948987, which is the DM send target expected by Discord instead of channel:<id>.

What was not tested: Live Discord DM delivery to the #78572 reporter's user id was not run because we do not have that user's bot/channel relationship locally; the DM fix was verified at the target-resolution layer that produced the reported Unknown Channel misroute, and live channel delivery verified the Discord send path after provider-prefixed normalization.

Verification

  • pnpm exec oxfmt --check --threads=1 extensions/discord/src/channel.ts extensions/discord/src/channel.test.ts extensions/discord/src/target-parsing.ts extensions/discord/src/normalize.ts extensions/discord/src/targets.test.ts extensions/discord/src/outbound-adapter.test.ts extensions/discord/src/outbound-session-route.test.ts CHANGELOG.md
  • pnpm test extensions/discord/src/channel.test.ts extensions/discord/src/targets.test.ts extensions/discord/src/normalize.test.ts extensions/discord/src/outbound-adapter.test.ts extensions/discord/src/outbound-session-route.test.ts src/agents/tools/message-tool.test.ts -- --run

@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord size: S maintainer Maintainer-authored PR labels May 6, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 6, 2026

Codex review: needs real behavior proof before merge.

Summary
The branch adds Discord parser and test coverage for discord:channel:<id> and discord:user:<id> targets while preserving legacy discord:<id> DM routing, plus a changelog entry.

Reproducibility: yes. by source inspection: current main parses discord:channel:<id> through the legacy discord: user-prefix path, and the linked issue's bare numeric DM target still defaults through normalizeDiscordMessagingTarget to a channel. I did not run live Discord during this read-only review.

Real behavior proof
Needs stronger real behavior proof before merge: The PR body lists tests and a local dry-run statement, but it does not provide after-fix terminal output, logs, screenshots, recordings, or linked artifacts; the dedicated proof check also failed. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, ask a maintainer to comment @clawsweeper re-review.

Next step before merge
Needs maintainer/contributor handling for missing real behavior proof, dirty mergeability, and the incorrect linked-issue closure claim; this is not a safe automated repair marker while contributor proof is required.

Security
Cleared: No concrete security or supply-chain regression was found; the diff is limited to Discord target parsing tests and changelog text, with no dependency, workflow, secret, or downloaded-code changes.

Review findings

  • [P2] Do not close the bare numeric Discord DM bug — CHANGELOG.md:57
Review details

Best possible solution:

Either retarget this PR to only provider-prefixed Discord channel parsing without closing the linked DM bug, or expand it to fix the actual allowFrom-aware bare numeric DM path with regression tests, a corrected changelog line, and real runtime proof.

Do we have a high-confidence way to reproduce the issue?

Yes by source inspection: current main parses discord:channel:<id> through the legacy discord: user-prefix path, and the linked issue's bare numeric DM target still defaults through normalizeDiscordMessagingTarget to a channel. I did not run live Discord during this read-only review.

Is this the best way to solve the issue?

No. Parsing provider-prefixed channel/user targets before the legacy shorthand is a good narrow fix for one misparse, but it is not sufficient to solve the linked target:"143..." DM failure without wiring allowFrom-aware resolution into the message-tool path.

Full review comments:

  • [P2] Do not close the bare numeric Discord DM bug — CHANGELOG.md:57
    The changed changelog entry ties this provider-prefixed channel parser to [Bug]: message tool action=send to Discord fails with "Unknown Channel" despite bot being connected #78572, but that report is about message(action="send") with a bare numeric Discord DM target. This diff still leaves normalizeDiscordMessagingTarget("123") as channel:123, so merging would close the linked issue while the reported DM path remains broken. Either remove the closing reference or wire the allowFrom-aware DM resolver into the message-tool path.
    Confidence: 0.91

Overall correctness: patch is incorrect
Overall confidence: 0.88

What I checked:

  • Current provider-prefixed misparse: On current main, parseDiscordTarget passes discord: through the legacy user prefix parser, so discord:channel:<id> is treated as a user id before this PR's proposed parser runs. (extensions/discord/src/target-parsing.ts:27, 97b07eaeaf38)
  • PR diff scope: The diff adds provider-prefixed parsing and tests for discord:channel:<id> / discord:user:<id>, but it does not change the allowFrom-aware bare numeric DM path implicated by the linked issue. (extensions/discord/src/target-parsing.ts:21, 4fc630fe399d)
  • Linked issue path differs: The linked report and follow-up comments describe message(action="send") failing for a bare numeric Discord user id target, with channels.resolve discord:<userId> still resolving correctly.
  • Bare numeric target still defaults to channel: normalizeDiscordMessagingTarget still calls parseDiscordTarget(raw, { defaultKind: "channel" }), while Discord docs say effective DM allowFrom entries should be treated as user DM targets for compatibility. (extensions/discord/src/normalize.ts:3, 97b07eaeaf38)
  • Registered Discord target resolver lacks allowFrom resolver: The Discord messaging registration exposes only looksLikeId and a hint in targetResolver; the allowFrom-aware conversion is not wired into the generic message-tool target resolution path here. (extensions/discord/src/channel.ts:326, 97b07eaeaf38)
  • Real behavior proof check failed: The GitHub Real behavior proof check failed with an annotation requiring after-fix evidence from a real setup; the PR body has tests and a dry-run statement but no terminal/log/live-output proof. (4fc630fe399d)

Likely related people:

  • Squirbie: Authored the merged Discord allowFrom DM disambiguation work that current issue triage identified as relevant to the unresolved bare numeric DM path. (role: introduced adjacent behavior; confidence: high; commits: 94a85e77dea8; files: extensions/discord/src/normalize.ts, extensions/discord/src/target-resolver.ts, extensions/discord/src/outbound-adapter.ts)
  • steipete: Co-authored/merged adjacent Discord allowFrom work, owns recent outbound message-action lifecycle changes, and current local blame shows recent maintenance of the Discord target parsing files. (role: recent maintainer and adjacent owner; confidence: high; commits: 94a85e77dea8, 2ead1502c9bf, 167e43345acc; files: extensions/discord/src/normalize.ts, extensions/discord/src/target-parsing.ts, extensions/discord/src/outbound-session-route.ts)
  • scoootscooob: Moved the Discord channel implementation into extensions/discord, establishing the current plugin-owned files affected by this PR. (role: major refactor author; confidence: medium; commits: 5682ec37fada; files: extensions/discord/src/channel.ts, extensions/discord/src/normalize.ts, extensions/discord/src/targets.ts)

Remaining risk / open question:

Codex review notes: model gpt-5.5, reasoning high; reviewed against 97b07eaeaf38.

@Patrick-Erichsen Patrick-Erichsen force-pushed the pe/discord-provider-prefixed-channel-target branch from 4fc630f to 72fd4ff Compare May 6, 2026 20:55
@Patrick-Erichsen Patrick-Erichsen force-pushed the pe/discord-provider-prefixed-channel-target branch from c06f137 to fca15d4 Compare May 6, 2026 21:22
@Patrick-Erichsen Patrick-Erichsen merged commit 5135662 into main May 6, 2026
160 of 223 checks passed
@Patrick-Erichsen Patrick-Erichsen deleted the pe/discord-provider-prefixed-channel-target branch May 6, 2026 21:26
vincentkoc added a commit that referenced this pull request May 6, 2026
rogerdigital pushed a commit to rogerdigital/openclaw that referenced this pull request May 7, 2026
steipete pushed a commit that referenced this pull request May 7, 2026
* fix(discord): parse provider-prefixed channel targets

* fix(discord): resolve allowlisted numeric dm targets

(cherry picked from commit 5135662)
@pkmatt
Copy link
Copy Markdown

pkmatt commented May 7, 2026

Regression still present in v2026.5.7: Outbound-initiated message tool action=send to Discord DMs still fails with Unknown Channel after this fix was merged. Tested immediately after upgrading — same error.

channels.resolve discord:1439091261670948987 resolves correctly, but outbound-initiated sends fail. Email announce fallback confirmed working as workaround.

Original issue: #78572

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
* fix(discord): parse provider-prefixed channel targets

* fix(discord): resolve allowlisted numeric dm targets
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
rogerdigital pushed a commit to rogerdigital/openclaw that referenced this pull request May 9, 2026
* fix(discord): parse provider-prefixed channel targets

* fix(discord): resolve allowlisted numeric dm targets
rogerdigital pushed a commit to rogerdigital/openclaw that referenced this pull request May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: discord Channel integration: discord maintainer Maintainer-authored PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: message tool action=send to Discord fails with "Unknown Channel" despite bot being connected

2 participants