openclaw - ✅(Solved) Fix [Bug]: WhatsApp outbound sends fail with 'No active WhatsApp Web listener' despite channel being connected [2 pull requests, 4 comments, 5 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#49345Fetched 2026-04-08 00:56:13
View on GitHub
Comments
4
Participants
5
Timeline
12
Reactions
1
Timeline (top)
commented ×4cross-referenced ×3subscribed ×2closed ×1

When attempting to send outbound WhatsApp messages via openclaw message send or sessions_send RPC tool, the gateway returns UNAVAILABLE: No active WhatsApp Web listener (account: default) — even though openclaw channels status shows linked, running, connected and inbound messages + auto-replies work perfectly.

Error Message

  1. Error: GatewayClientRequestError: No active WhatsApp Web listener
  • Delivery queue retries (stuck with same error)
  • RPC send fails: ⇄ res ✗ send errorCode=UNAVAILABLE errorMessage=Error: No active WhatsApp Web listener

Root Cause

Root Cause Hypothesis

Fix Action

Fix / Workaround

The web-auto-reply subsystem and the agent session system run in parallel with isolated state. Messages sent via wacli (whatsmeow) or RPC don't appear in the web-auto-reply session context, making bidirectional context-aware conversations with third parties impossible without workarounds.

PR fix notes

PR #50384: Fix WhatsApp duplicated active-listener state across bundled runtime chunks

Description (problem / solution / changelog)

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: WhatsApp outbound sends can fail with No active WhatsApp Web listener even while WhatsApp is connected and inbound messaging still works, because the active listener registry is duplicated across bundled runtime chunks.
  • Why it matters: message send, proactive outbound delivery, and some recovery/retry paths can fail while the channel still appears healthy and other WhatsApp flows continue to work.
  • What changed: moved the active WhatsApp listener registry to a process-wide globalThis singleton so all chunks share the same listener state instead of maintaining separate module-scoped Map instances.
  • What did NOT change (scope boundary): this PR does not add a fallback transport, does not change channel health/status policy, and does not introduce any new delivery path beyond fixing the existing listener lookup.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #49345
  • Closes #49209
  • Closes #49149
  • Closes #50166
  • Closes #49217

User-visible / Behavior Changes

  • WhatsApp outbound sends are able to resolve the active listener consistently across bundled runtime chunks.
  • This removes a class of failures where outbound sends report No active WhatsApp Web listener even though WhatsApp inbound and other outbound paths are still functioning.
  • No config or default changes.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

None.

Repro + Verification

Environment

  • OS: Linux
  • Runtime/container: local OpenClaw source checkout
  • Model/provider: Any
  • Integration/channel (if any): WhatsApp
  • Relevant config (redacted): standard WhatsApp account config with active listener registration

Steps

  1. Run a build where WhatsApp listener state is written from one bundled chunk and read from another.
  2. Connect WhatsApp successfully so inbound messaging is active.
  3. Trigger an outbound send path that resolves the listener through a different bundled runtime chunk.

Expected

  • Outbound send paths should resolve the same active WhatsApp listener state used by the connected runtime.

Actual

  • Before this change, different chunks can hold different module-scoped listener Map instances, causing outbound sends to fail with No active WhatsApp Web listener.
  • After this change, all chunks share a single process-wide listener registry via globalThis.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
  • Ran targeted test file extensions/whatsapp/src/send.test.ts
  • Added and ran extensions/whatsapp/src/active-listener.test.ts
  • Confirmed listener storage is pinned to a shared globalThis registry
  • Confirmed existing targeted WhatsApp send tests still pass after the registry change
  • Confirmed from live logs that WhatsApp inbound and some outbound paths succeed while other outbound paths fail with No active WhatsApp Web listener, matching the duplicated-state diagnosis
  • Edge cases checked:
  • normal in-process listener send path still works
  • no-listener case still throws the same helpful error
  • account-scoped listener registration and lookup still work
  • poll/reaction/send targeted tests still pass under the shared registry implementation
  • What you did not verify:
  • full end-to-end validation of the patched build on the production-style packaged install
  • broader health/status reconciliation beyond the listener registry itself
  • every possible bundled runtime path outside the targeted WhatsApp tests and log-based diagnosis

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

None.

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly:
  • revert this PR/commit
  • Files/config to restore:
  • extensions/whatsapp/src/active-listener.ts
  • extensions/whatsapp/src/active-listener.test.ts
  • extensions/whatsapp/src/send.test.ts
  • Known bad symptoms reviewers should watch for:
  • listener lookups still diverging between chunks
  • unexpected listener leakage across accounts
  • outbound WhatsApp sends failing despite successful listener registration

Risks and Mitigations

  • Risk: this change makes the active WhatsApp listener registry process-global via globalThis, so if that registry contract is wrong, multiple WhatsApp runtime paths could now share incorrect state instead of isolated incorrect state.
  • Mitigation: the current behavior already fails in real usage because the listener state is unintentionally split across bundled chunks; this PR replaces those accidental duplicate stores with one explicit shared registry, while preserving the same public behavior and listener API.

Changed files

  • extensions/whatsapp/src/active-listener.test.ts (modified, +11/-3)
  • extensions/whatsapp/src/active-listener.ts (modified, +0/-14)

PR #47433: fix(whatsapp): use globalThis singleton for active-listener Map

Description (problem / solution / changelog)

Summary

  • The listeners Map in extensions/whatsapp/src/active-listener.ts is duplicated across 7+ output chunks by Rolldown code-splitting
  • setActiveWebListener() populates the Map in one chunk, but requireActiveWebListener() reads from a different chunk's copy
  • Outbound sends via the message tool always fail with "No active WhatsApp Web listener" while auto-replies (which bypass the Map via direct socket references) work fine
  • Pin both the listeners Map and _currentListener to globalThis so all chunk-local copies resolve to the same shared instance

Test plan

  • Verify existing send.test.ts passes
  • Start gateway with WhatsApp linked
  • Send media via message tool — should succeed instead of throwing "No active WhatsApp Web listener"
  • Verify auto-reply path still works
  • Verify getActiveWebListener() / requireActiveWebListener() return the listener registered by setActiveWebListener() even when called from a different chunk

Fixes #14406

🤖 Generated with Claude Code

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/whatsapp/src/active-listener.ts (modified, +29/-3)
RAW_BUFFERClick to expand / collapse

Summary

When attempting to send outbound WhatsApp messages via openclaw message send or sessions_send RPC tool, the gateway returns UNAVAILABLE: No active WhatsApp Web listener (account: default) — even though openclaw channels status shows linked, running, connected and inbound messages + auto-replies work perfectly.

Steps to Reproduce

  1. Link WhatsApp with openclaw channels login --channel whatsapp
  2. Confirm openclaw channels status shows connected
  3. Run: openclaw message send --channel whatsapp --target +XXXXXXXXXXX --message "test"
  4. Error: GatewayClientRequestError: No active WhatsApp Web listener

What Works ✅

  • Inbound messages received correctly
  • Auto-replies to existing conversations (via web-auto-reply subsystem)

What Fails ❌

  • openclaw message send --channel whatsapp
  • sessions_send RPC tool
  • Delivery queue retries (stuck with same error)

Root Cause Hypothesis

The web-auto-reply worker registers its own WebSocket/Baileys connection and handles replies correctly. However, the gateway's RPC send path (gateway/ws) looks for a separate "WhatsApp Web listener" registration that never happens — the two subsystems don't share the same socket/Baileys instance reference.

Log evidence:

  • web-auto-reply sends successfully: [whatsapp] Auto-replied to +XXXXXXXXXX
  • RPC send fails: ⇄ res ✗ send errorCode=UNAVAILABLE errorMessage=Error: No active WhatsApp Web listener
  • Both happening simultaneously with the same linked account

Related Issue

The web-auto-reply subsystem and the agent session system run in parallel with isolated state. Messages sent via wacli (whatsmeow) or RPC don't appear in the web-auto-reply session context, making bidirectional context-aware conversations with third parties impossible without workarounds.

Environment

  • Version: 2026.3.13
  • OS: Linux arm64 (Oracle Cloud)
  • Node: v22.22.1
  • Gateway mode: local/loopback
  • Channel: WhatsApp (Baileys/Web)

extent analysis

Fix Plan

To resolve the issue, we need to ensure that the WhatsApp Web listener is registered and shared between the web-auto-reply subsystem and the gateway's RPC send path.

Here are the concrete steps:

  • Modify the web-auto-reply worker to register the WhatsApp Web listener with the gateway.
  • Update the gateway's RPC send path to use the registered WhatsApp Web listener.

Example code changes:

// web-auto-reply worker
const baileys = require('@adiwajshing/baileys');
const gateway = require('./gateway');

// Register WhatsApp Web listener with the gateway
const whatsappListener = baileys.createWhatsAppWebListener();
gateway.registerWhatsAppListener(whatsappListener);

// Gateway's RPC send path
const whatsappListener = gateway.getWhatsAppListener();
if (!whatsappListener) {
  throw new Error('No active WhatsApp Web listener');
}
// Use the registered WhatsApp Web listener to send messages
whatsappListener.sendMessage('+XXXXXXXXXXX', 'test');

Verification

To verify that the fix worked, follow these steps:

  • Run openclaw channels login --channel whatsapp to link WhatsApp.
  • Confirm openclaw channels status shows connected.
  • Run openclaw message send --channel whatsapp --target +XXXXXXXXXXX --message "test" to send an outbound message.
  • Check the logs for successful message delivery.

Extra Tips

  • Ensure that the web-auto-reply worker and the gateway's RPC send path are using the same Baileys instance reference.
  • Consider implementing a mechanism to share the WhatsApp Web listener registration between subsystems to avoid similar issues in the future.
  • Review the related issue and consider implementing a workaround to enable bidirectional context-aware conversations with third parties.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING