Environment
- OpenClaw: v2026.4.2 (d74a122)
- OS: Ubuntu 24.04 (Proxmox LXC)
- Node: v22.22.1
- Discord: 1 guild, 1 channel, groupPolicy: allowlist, single account
Description
Discord adapter connects, resolves guild/channel/users, logs client initialized as ... ; awaiting gateway readiness, then never reaches READY. Outbound (REST API) works fine; inbound (WebSocket gateway) is completely dead. The health monitor cycles stale-socket restarts every ~35 minutes indefinitely.
This persists across:
- Hot reloads (SIGUSR1 /
openclaw gateway restart)
- Full
systemctl --user restart openclaw-gateway
- Full VM reboot
Root cause confirmation
Raw WebSocket test with the same token, intents (46721), and ws module (v8.19.0 from the same node_modules) connects and receives READY in under 1 second, every time. The issue is inside the @buape/carbon gateway plugin lifecycle, not the network/token/intents.
This matches #56492 — the Client constructor calls plugin.registerClient?.(this) without await, and SafeGatewayPlugin.registerClient is async (fetches gateway metadata, then calls super.registerClient which opens the WebSocket).
Workaround: --verbose flag
Adding --verbose to the gateway startup command reliably fixes the issue:
ExecStart=/usr/bin/node .../dist/entry.js gateway --port 18789 --verbose
Without --verbose: gateway hangs at "awaiting gateway readiness" 100% of the time (tested across multiple restarts and a full VM reboot).
With --verbose: gateway connects and reaches READY immediately. Tested with 60+ messages received, 0 reconnects, 0 errors.
Why --verbose likely works
Verbose mode adds synchronous log I/O calls (console.log) in the gateway debug event handler. This changes Node.js event loop scheduling — the additional I/O microtask yields appear to give the un-awaited registerClient() async chain time to complete the WebSocket handshake before the polling/timeout logic proceeds.
Without verbose logging, the event loop likely runs the waitForGatewayReady polling loop tightly enough that it races past the WebSocket connection establishment.
Startup log comparison
Failing start (no --verbose):
[discord] [default] starting provider (@Fitz)
[discord] channels resolved: XXXXXXXX/XXXXXXXXX (guild:HomeLan; channel:openclaw)
[discord] users resolved: XXXXXXXXXXXXXXX
[discord] channel users resolved:XXXXXXXXXXXXXXX
[discord] client initialized as XXXXXXXXXXXXXXXX (Fitz); awaiting gateway readiness
(silence — no further discord logs ever)
Working start (with --verbose):
discord: config dm=on dmPolicy=allowlist allowFrom=XXXXXXXXXXXXX ...
[discord] [default] starting provider (@Fitz)
[discord] channels resolved: ...
[discord] startup [default] gateway-debug 1671ms Gateway websocket opened
[discord] client initialized as XXXXXXXXXXXXXXXXXXXXX (Fitz); awaiting gateway readiness
(discord fully functional — receives messages, delivers replies)
Related issues
Suggested fix
The registerClient call in the Carbon Client constructor needs to be awaited, or the gateway plugin needs a synchronous initialization path that does not depend on async I/O completing before the constructor returns.
Environment
Description
Discord adapter connects, resolves guild/channel/users, logs
client initialized as ... ; awaiting gateway readiness, then never reaches READY. Outbound (REST API) works fine; inbound (WebSocket gateway) is completely dead. The health monitor cyclesstale-socketrestarts every ~35 minutes indefinitely.This persists across:
openclaw gateway restart)systemctl --user restart openclaw-gatewayRoot cause confirmation
Raw WebSocket test with the same token, intents (46721), and
wsmodule (v8.19.0 from the samenode_modules) connects and receives READY in under 1 second, every time. The issue is inside the@buape/carbongateway plugin lifecycle, not the network/token/intents.This matches #56492 — the
Clientconstructor callsplugin.registerClient?.(this)withoutawait, andSafeGatewayPlugin.registerClientis async (fetches gateway metadata, then callssuper.registerClientwhich opens the WebSocket).Workaround:
--verboseflagAdding
--verboseto the gateway startup command reliably fixes the issue:Without
--verbose: gateway hangs at "awaiting gateway readiness" 100% of the time (tested across multiple restarts and a full VM reboot).With
--verbose: gateway connects and reaches READY immediately. Tested with 60+ messages received, 0 reconnects, 0 errors.Why
--verboselikely worksVerbose mode adds synchronous log I/O calls (
console.log) in the gateway debug event handler. This changes Node.js event loop scheduling — the additional I/O microtask yields appear to give the un-awaitedregisterClient()async chain time to complete the WebSocket handshake before the polling/timeout logic proceeds.Without verbose logging, the event loop likely runs the
waitForGatewayReadypolling loop tightly enough that it races past the WebSocket connection establishment.Startup log comparison
Failing start (no --verbose):
Working start (with --verbose):
Related issues
registerClientSuggested fix
The
registerClientcall in the CarbonClientconstructor needs to be awaited, or the gateway plugin needs a synchronous initialization path that does not depend on async I/O completing before the constructor returns.