Channel plugin subprocess can become a networking zombie — gateway never connects, no error surfaced

Resolved 💬 3 comments Opened Mar 31, 2026 by snohub Closed Apr 3, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

Channel plugin subprocesses (tested with Discord, previously hit with Telegram) can enter a state where the bun process is alive but has zero TCP connections — the Discord.js gateway WebSocket never establishes. The process runs indefinitely as a networking zombie with no error surfaced to the user.

Diagnosis steps that confirmed the issue:

  1. ps aux | grep bun — plugin process running (4+ hours uptime)
  2. ss -tnp | grep <PID> — zero TCP connections
  3. No inbox/ directory created (no messages ever received)
  4. No access.json created (pairing flow never triggered)
  5. Standalone test with identical token + discord.js code connects immediately
  6. Token validated via Discord REST API (GET /users/@me → 200)

Root cause: client.login(TOKEN) may resolve without the underlying WebSocket completing the gateway handshake. If the first connection attempt fails (transient DNS timeout, network blip during startup), discord.js auto-reconnect may never engage. The .catch() on login() only handles Promise rejection, not a post-resolve WebSocket failure.

Why this is hard to catch: Plugin stderr goes to the MCP socket pipe, not the user's terminal. The "gateway connected as ..." message (written to stderr) is never visible. There is no healthcheck, no watchdog, and no way to restart a channel plugin without restarting the entire Claude Code session.

What Should Happen?

  1. Startup confirmation — surface the "gateway connected" (or failure) message visibly to the user, not just stderr
  2. Health monitoring — detect "process alive but not connected" zombie state and either retry or warn the user
  3. Hot restart — allow restarting a channel plugin subprocess without restarting the full Claude Code session
  4. Timeout — if the gateway doesn't connect within N seconds of launch, surface an error

Steps to Reproduce

  1. Start Claude Code with --channels plugin:discord@claude-plugins-official
  2. (Intermittent) If the gateway WebSocket fails during the initial handshake, the process enters zombie state
  3. DM the bot — no response, no pairing code
  4. No error visible anywhere in the Claude Code session

Workaround

Kill the zombie bun process and restart the Claude Code session:

# Find the zombie
ps aux | grep bun | grep discord
# Verify it has no connections
ss -tnp | grep <PID>
# Kill it
kill <PID>
# Restart session
claude --channels plugin:discord@claude-plugins-official

Related Issues

  • #38585 — Plugin MCP server silently fails to start (different: our process does start)
  • #40576 — Discord DM routing fails after restart (different: our bot never connects in the first place)

Environment

  • Claude Code: latest
  • OS: Linux (WSL2)
  • Bun: 1.3.11
  • discord.js: 14.25.1
  • Plugin: discord@claude-plugins-official

Claude Model

Claude Opus 4.6

Is this a regression?

Not sure — first time setting up channels

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux (WSL2)

View original on GitHub ↗

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