Summary
openclaw message send successfully delivers the message but the process never exits, keeping the Node.js event loop alive indefinitely.
Reproduction
time openclaw message send --channel discord --target <channel-id> -m 'test'
# Message delivers in ~2s, "✅ Sent via Discord" prints, but process hangs forever
Root Cause Analysis
Traced through the bundled dist:
message send action calls runMessageAction → messageCommand() in program-DVsNBtwv.js:2812
messageCommand calls ensurePluginRegistryLoaded() which loads the Discord plugin and opens a WebSocket/REST client
- After
runMessageAction completes and output is printed, the function returns normally
runCommandWithRuntime() in cli-utils-r6pQ5iCT.js:18 simply awaits the action — no cleanup or process.exit()
- The Discord client's open WebSocket/connection keeps the Node.js event loop alive
- The process never exits
Other CLI commands (e.g., status) explicitly call runtime.exit(0) after completion, but the message send path does not.
Impact
Any script using execSync('openclaw message send ...') with a timeout will:
- Successfully deliver the message
- Hit the timeout waiting for exit
- Throw an error
- Retry (if retry logic exists) → duplicate messages
This was discovered via the SDLC runner which uses execSync with a 30s timeout and 3 retries — resulting in 2-3x duplicate Discord messages per status update.
Suggested Fix
Either:
- Add
process.exit(0) after the message send action completes (like other commands do)
- Or properly destroy/disconnect the plugin clients after one-shot CLI commands
Environment
- OpenClaw 2026.2.13 (203b5bd)
- Node v24.12.0
- macOS (arm64)
Summary
openclaw message sendsuccessfully delivers the message but the process never exits, keeping the Node.js event loop alive indefinitely.Reproduction
Root Cause Analysis
Traced through the bundled dist:
message sendaction callsrunMessageAction→messageCommand()inprogram-DVsNBtwv.js:2812messageCommandcallsensurePluginRegistryLoaded()which loads the Discord plugin and opens a WebSocket/REST clientrunMessageActioncompletes and output is printed, the function returns normallyrunCommandWithRuntime()incli-utils-r6pQ5iCT.js:18simply awaits the action — no cleanup orprocess.exit()Other CLI commands (e.g.,
status) explicitly callruntime.exit(0)after completion, but themessage sendpath does not.Impact
Any script using
execSync('openclaw message send ...')with a timeout will:This was discovered via the SDLC runner which uses
execSyncwith a 30s timeout and 3 retries — resulting in 2-3x duplicate Discord messages per status update.Suggested Fix
Either:
process.exit(0)after the message send action completes (like other commands do)Environment