Fix the per-chatId queue wedge in out-node.js when msg.payload.content is missing — root fix for issue #450 (WJ4IoT's report of "some senders stop working while others on the same bot keep going").
The bug
Long-latent since the per-chatId QueueManager landed on 2026-03-07 (6c44a22, "fix #300 fix #413"). Sequence:
- Sender receives a msg with
typeset but nocontent(the deterministic repro: command-node's "command detected" output for a/foocommand) enqueueMessage→queueManager.enqueue→processCurrentruns the work item synchronously- switch case hits
if (this.hasContent(msg)) { dispatch } break; hasContentwarns "msg.payload.content is empty", returns false, branch falls through tobreak- No
processResult/processErrorever fires →processing[chatId]staystrueforever - Every subsequent send to that chat queues but never starts
- Bot looks alive, no errors logged, only redeploy fixes it
Asymmetric per-chatId — only chats that ever saw an empty-content payload are stuck — which matches WJ4IoT's screenshot of "two senders frozen, two working" exactly.
Fix
hasContent now takes chatId and nodeDone as additional arguments. When content is missing it still warns, but ALSO calls nodeDone() (upstream promise chain settles) and queueManager.processNext(chatId) (queue head released, next message starts). All 29 callsites in the dispatch switch updated mechanically; the helper's return shape is unchanged so each case's if (this.hasContent(...)) reads the same.
Tests
2 new mocha regression cases:
- A sequence of empty-then-content on the same chat lets the second send through.
- The same pattern on two different chats preserves per-chatId isolation.
241 mocha cases passing (was 239).
V18 status
The same fix is on the migration/ntba-v1 branch (commit d469083) and will land in V18.0.0-beta.1 when that releases. Issue #448 tracks the V18 migration.