[BUG] Discord Channels Plugin DM bug

Resolved 💬 2 comments Opened Mar 29, 2026 by FelixCulpah Closed Apr 14, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Discord plugin: DM routing fails after Claude Code restarts; approved/ directory wiped on update

Two related problems in the discord plugin (v0.0.4) that together make DM routing unreliable in long-running deployments.

---

Issue 1: DM routing silently fails after Claude Code/plugin restart

After Claude Code restarts (e.g. auto-update), the MCP reply tool fails for DM channels with:

reply failed: channel <dm_channel_id> is not allowlisted — add via /discord:access

This occurs even when the sender's user ID is correctly listed in access.json → allowFrom.

Root cause (from server.ts): when the Discord.js client restarts and fetches a DM channel cold, ch.recipientId is null — the gateway hasn't delivered the channel object yet. The allowFrom check fails even though the user is correctly listed.

Workaround: use the Discord REST API directly (POST /channels/{id}/messages) — stateless, always works.

Suggested fix: pre-populate the DM channel cache on startup for all allowFrom user IDs, or fall back to a user ID lookup when recipientId is null.

Issue 2: approved/ directory wiped on Claude Code auto-update; no idempotency on pairing ceremony

The ~/.claude/channels/discord/approved/ directory is deleted when Claude Code auto-updates and reinitializes the plugin.

Secondary issue: any attempt to recreate a file in approved/<senderId> to restore routing causes checkApprovals() to fire "Paired! Say hi to Claude." again — no idempotency check exists. The poll-and-delete loop treats every new file as a fresh pairing ceremony. In a long-running deployment with automation watching for the missing file, this results in the pairing message firing on every poll cycle.

Suggested fixes:

  • Persist the approved/ directory across updates (treat as user state, not plugin ephemeral state)
  • Or separate the routing map from the pairing ceremony trigger — store confirmed DM mappings in access.json under a dmChannels key, and only send "Paired!" on genuinely new pairings

---

Environment

  • Plugin: discord v0.0.4
  • Deployment: long-running always-on instance, Claude Code auto-updates enabled
  • No custom plugin modifications

What Should Happen?

DM channel with approved users should stay accessible to the agent across updates to the client, even in a persistent tmux terminal session.

Error Messages/Logs

Steps to Reproduce

Tmux code session - auto update client on pi.

Claude Model

Not sure / Multiple models

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.83

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Other

Additional Information

_No response_

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗