Skip to content

WhatsApp outbound sends fail: dual Map instance bug in active-listener across bundles #46414

@e1th4nUwU

Description

@e1th4nUwU

Summary

openclaw message send --channel whatsapp fails with No active WhatsApp Web listener (account: default) even when the gateway is running, WhatsApp is linked, inbound messages are received, and auto-replies send successfully.

Version

2026.3.13 (reproduced on 2026.3.12 as well, update did not fix it)

Symptoms

  • openclaw message send --channel whatsapp --target ...GatewayClientRequestError: No active WhatsApp Web listener (account: default)
  • Inbound messages arrive correctly
  • Auto-replies (via web-auto-reply module) send correctly — text and files
  • openclaw channels status --probe shows WhatsApp as connected
  • openclaw channels capabilities --channel whatsapp shows Probe: unavailable
  • The error is consistent across gateway restarts and re-links

Root Cause

Two separate bundle files each define their own listeners = new Map() for the WhatsApp Web active-listener registry (sourced from src/web/active-listener.ts):

  • auth-profiles-DRjqKE3G.js — defines requireActiveWebListener(), used by the gateway WS tool handler (gateway-cli-CuZs0RlJ.js) when processing send RPC calls
  • model-selection-CU2b7bN6.js — defines setActiveWebListener(), used by the WhatsApp channel runtime (auth-profiles.runtime-BoPFCfb5.jsweb-Cz_8x_nz.js) when the channel starts up

Because these are two distinct Map instances in two different bundle files, the channel registers the listener in model-selection's Map while the WS tool handler looks in auth-profiles's Map — and always finds it empty.

The auto-reply path works because it calls setActiveWebListener and sendMessageWhatsApp from the same bundle (web-Cz_8x_nz.js / model-selection-CU2b7bN6.js), so it never crosses the Map boundary.

Workaround

Patch both files to share a single Map via globalThis:

// In both auth-profiles-DRjqKE3G.js and model-selection-CU2b7bN6.js
// Replace:
const listeners = /* @__PURE__ */ new Map();
// With:
globalThis.__ocWebListeners = globalThis.__ocWebListeners || new Map(); const listeners = globalThis.__ocWebListeners;

After patching and restarting the gateway, both openclaw message send (text and files/PDFs) work correctly.

Expected Fix

Ensure active-listener.ts is only bundled once and shared between the gateway WS handler and the WhatsApp channel runtime, so setActiveWebListener and requireActiveWebListener operate on the same Map instance.

Reproduction Steps

  1. Install openclaw, configure WhatsApp Web channel
  2. Start the gateway: openclaw gateway start
  3. Link WhatsApp: openclaw channels login --channel whatsapp
  4. Verify channel is connected: openclaw channels status --probe → shows connected
  5. Try to send: openclaw message send --channel whatsapp --target +1234567890 --message "test"
  6. GatewayClientRequestError: No active WhatsApp Web listener (account: default)
  7. Send an inbound message from the linked phone → gateway receives it and auto-replies successfully

Platform

  • Linux (Fedora 43, kernel 6.17.7-300.fc43.x86_64)
  • Node.js 22.22.1
  • openclaw installed via npm global (pnpm)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions