Skip to content

[Bug]: Discord DM heartbeats erroneously resolve user:<snowflake> to channel:<snowflake> #75359

@luna-system

Description

@luna-system

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

Heartbeat messages targeting discord DMs fail permanently. Attached is a full bug report generated by kimi-code (who found the bug as well).

openclaw-discord-dm-heartbeat-bug-report.md

Steps to reproduce

  1. With agents.list.<id>.heartbeat
    • Set target to "discord"
    • Set to to "user:"
    • Set directPolicy to "allow" **
    • Set accountId to explicit channels Id **
  2. With channels.discord
    • Set showAlerts, useIndicator, and showOk to true **
  3. Set explicit allowFrom for agents in channels **
  4. Wait for or trigger a heartbeat

** these may not matter here and were set explicitly as part of troubleshooting this bug. these agents have already been successfully paired, so allowFrom shouldn't be necessary, and indeed it's not necessary for an identical config for Telegram.

Expected behavior

Heartbeat message should be delivered to Discord DMs. Note that our configuration explicitly has all heartbeat messages enabled for discord.

Actual behavior

"Unknown Channel" error in heartbeat logs
Permafailure state of messages in delivery-queue, due to to field being clobbered into channel:<my user snowflake>

OpenClaw version

2026.4.24

Operating system

arch

Install method

npm global

Model

kimi-code/kimi-for-coding

Provider / routing chain

openclaw->kimi-code->kimi-for-coding

Additional provider/model setup details

No response

Logs, screenshots, and evidence

{"0":"{\"subsystem\":\"gateway/heartbeat\"}","1":{"error":"Unknown Channel"},"2":"heartbeat failed: Unknown Channel","_meta":{"runtime":"node","runtimeVersion":"24.14.1","hostname":"unknown","name":"{\"subsystem\":\"gateway/heartbeat\"}","parentNames":["openclaw"],"date":"2026-04-30T22:33:09.804Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"file:///home/luna/.npm-global/lib/node_modules/openclaw/dist/subsystem-CWI_MDy_.js:336:51","fileName":"subsystem-CWI_MDy_.js","fileNameWithLine":"subsystem-CWI_MDy_.js:336","fileColumn":"51","fileLine":"336","filePath":".npm-global/lib/node_modules/openclaw/dist/subsystem-CWI_MDy_.js","filePathWithLine":".npm-global/lib/node_modules/openclaw/dist/subsystem-CWI_MDy_.js:336","method":"logToFile"}},"time":"2026-04-30T17:33:09.804-05:00"}
{"0":"{\"subsystem\":\"gateway/delivery-recovery\"}","1":"Retry failed for delivery 6731ca8c-d4be-4aa0-8ce2-603e77fbdd18: Unknown Channel","_meta":{"runtime":"node","runtimeVersion":"24.14.1","hostname":"unknown","name":"{\"subsystem\":\"gateway/delivery-recovery\"}","parentNames":["openclaw"],"date":"2026-05-01T00:50:03.347Z","logLevelId":4,"logLevelName":"WARN","path":{"fullFilePath":"file:///home/luna/.npm-global/lib/node_modules/openclaw/dist/subsystem-CWI_MDy_.js:337:14","fileName":"subsystem-CWI_MDy_.js","fileNameWithLine":"subsystem-CWI_MDy_.js:337","fileColumn":"14","fileLine":"337","filePath":".npm-global/lib/node_modules/openclaw/dist/subsystem-CWI_MDy_.js","filePathWithLine":".npm-global/lib/node_modules/openclaw/dist/subsystem-CWI_MDy_.js:337","method":"logToFile"}},"time":"2026-04-30T19:50:03.347-05:00"}

Impact and severity

Severity: Very High
Frequency: Always
Consequence: Agent alerts sent to the user are never delivered and fail permanently

Additional information

The kimi-code agent that did the bug hunting proposed a simple fix that we'll include below. We recommend not skipping the full agent bug report that is attached above, since it also points out another tangential issue, and a thorough breakdown of the problem.

Proposed Fix

In dist/extensions/discord/channel-CGp7scNs.js, change line 346:

  function parseDiscordExplicitTarget(raw) {
      try {
          const target = parseDiscordTarget(raw, { defaultKind: "channel" });
          if (!target) return null;
          return {
-             to: target.id,
+             to: target.normalized,
              chatType: target.kind === "user" ? "direct" : "channel"
          };
      } catch {
          return null;
      }
  }

target.normalized preserves the full user:<id> or channel:<id> string, preventing downstream code from reclassifying the target.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingbug:behaviorIncorrect behavior without a crash

    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