hermes - 💡(How to fix) Fix [Bug]: fix(whatsapp): DM pairing fails — self-chat default, allowlist conflict, missing dm_policy bridge

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…

Error Message

The user sends a DM to the bot — nothing happens. No pairing code, no response, no error. The message is silently dropped.

Additional Logs / Traceback (optional)

Root Cause

Four root causes work together to break pairing:

Fix Action

Fix / Workaround

  1. Without any workarounds (default configuration): The user sends a DM to the bot — nothing happens. No pairing code, no response, no error. The message is silently dropped. From the bridge: Message rejected with no surface-level indication to the user:

  2. With WHATSAPP_MODE=bot + WHATSAPP_ALLOWED_USERS=*: Same as above — gateway sees "*" in the allowlist and authorizes the user immediately, bypassing the pairing handshake:

# gateway/run.py ~7264:
if "*" in allowed_ids:
    return True  # Bypasses pairing!
  1. With all workarounds applied (env vars + bridge.js patch): ✅ Pairing code IS sent and hermes pairing list shows: Pending Pairing Requests (1): Platform Code User ID Name Retries Expires In whatsapp bff982cd 197478351684846 . But hermes pairing approve whatsapp bff982cd returns: Code 'BFF982CD' not found or expired for platform 'whatsapp'. …despite the code clearly appearing in hermes pairing list, requiring manual insertion into whatsapp-approved.json.
  2. After hermes pairing revoke: The revoked user sends another DM — no new pairing code arrives. The old rate limit entry in _rate_limits.json persists and blocks re-generation. Manual deletion of the file required.

Code Example

# gateway/run.py ~7264:
if "*" in allowed_ids:
    return True  # Bypasses pairing!

---

Report (system info)	paste.rs/dOOKP
agent.log	paste.rs/BQuWP
gateway.log	paste.rs/u7Zj8
desktop.log	paste.rs/xGnXI

---
RAW_BUFFERClick to expand / collapse

Bug Description

i don't understand coding so i let my ai help me for everything below 😅

DM pairing on WhatsApp is completely non-functional. Users who send a DM to the bot never receive a pairing code — the message is either silently dropped or handled as if the user is already authorized, bypassing the pairing handshake entirely.

Four root causes work together to break pairing:

  1. WHATSAPP_MODE defaults to self-chat — the bridge silently drops all messages from external numbers before they reach the gateway. Pairing can never start because the messages never arrive.
  2. WHATSAPP_ALLOWED_USERS conflict between bridge and gateway — the bridge requires this env var to forward messages (empty = reject all), but setting it to * makes the gateway skip the pairing handshake entirely and authorize everyone automatically.
  3. dm_policy: pairing set in config.yaml doesn't reach the WhatsApp adapter — the adapter reads from config.extra which never receives the value from platforms.whatsapp.dm_policy. Falls back to default "open", silently skipping the pairing flow.
  4. _get_unauthorized_dm_behavior doesn't include WhatsApp — only WeCom, Weixin, Yuanbao, and QQBot are checked for config-driven dm_policy. WhatsApp is excluded even though it supports dm_policy and has enforces_own_access_policy = True.

Steps to Reproduce

  1. Set up Hermes with WhatsApp bridge (separate phone number, WHATSAPP_MODE=bot)
  2. Configure platforms.whatsapp.dm_policy: pairing in config.yaml
  3. Start gateway
  4. Send a DM from a different phone number
  5. Expected: User receives "Pairing code: ABCDEFGH"
  6. Actual: No pairing code is sent. Depending on env var configuration, the message is either:
  • Silently dropped (bridge rejects non-self messages in default self-chat mode)
  • Processed without pairing (gateway bypasses when WHATSAPP_ALLOWED_USERS=*)

Expected Behavior

Expected: User receives "Pairing code: XXXXXX"

Actual Behavior

  1. Without any workarounds (default configuration): The user sends a DM to the bot — nothing happens. No pairing code, no response, no error. The message is silently dropped. From the bridge: Message rejected with no surface-level indication to the user:

// bridge.js internal log: event: 'ignored', reason: 'self_chat_mode_rejects_non_self' The bridge log entry is the only trace — the sending user sees nothing.

  1. With WHATSAPP_MODE=bot set, but nothing else: The model responds directly to the unauthorized user as if they're already approved. No pairing code is generated or sent. Gateway log shows: Unauthorized user 197478351634596 (platform: whatsapp) … But the unauthorized handler falls through to dm_policy: open because the dm_policy value from config.yaml never reaches the adapter, and the env var WHATSAPP_DM_POLICY defaults to "open".

  2. With WHATSAPP_MODE=bot + WHATSAPP_ALLOWED_USERS=*: Same as above — gateway sees "*" in the allowlist and authorizes the user immediately, bypassing the pairing handshake:

# gateway/run.py ~7264:
if "*" in allowed_ids:
    return True  # Bypasses pairing!
  1. With all workarounds applied (env vars + bridge.js patch): ✅ Pairing code IS sent and hermes pairing list shows: Pending Pairing Requests (1): Platform Code User ID Name Retries Expires In whatsapp bff982cd 197478351684846 . But hermes pairing approve whatsapp bff982cd returns: Code 'BFF982CD' not found or expired for platform 'whatsapp'. …despite the code clearly appearing in hermes pairing list, requiring manual insertion into whatsapp-approved.json.
  2. After hermes pairing revoke: The revoked user sends another DM — no new pairing code arrives. The old rate limit entry in _rate_limits.json persists and blocks re-generation. Manual deletion of the file required.

Affected Component

Gateway (Telegram/Discord/Slack/WhatsApp)

Messaging Platform (if gateway-related)

WhatsApp

Debug Report

Report (system info)	paste.rs/dOOKP
agent.log	paste.rs/BQuWP
gateway.log	paste.rs/u7Zj8
desktop.log	paste.rs/xGnXI

Operating System

windows 11

Python Version

Python 3.11.15

Hermes Version

v0.15.1

Additional Logs / Traceback (optional)

Root Cause Analysis (optional)

Root Cause Four independent bugs form a chain that collectively makes WhatsApp DM pairing impossible — each layer silently drops or bypasses the pairing handshake, so the user never sees a pairing code.

Proposed Fix (optional)

  • Fixes Required (by priority) :
  1. gateway/platforms/whatsapp.py line 320 — Change default WHATSAPP_MODE from "self-chat" to "bot" when a WhatsApp session exists. This stops the bridge from silently dropping all external DMs before they reach the gateway.

  2. gateway/run.py line 7264 — When WHATSAPP_ALLOWED_USERS contains "*", don't return True immediately. Check dm_policy first: if it's "pairing", let the message fall through to the pairing handshake instead of bypassing it.

  3. gateway/run.py line 7318 — Add Platform.WHATSAPP (and any platform with enforces_own_access_policy = True) to _get_unauthorized_dm_behavior so the dm_policy from config.yaml is actually resolved for WhatsApp, not just WeCom/Weixin/Yuanbao/QQBot.

  4. gateway/run.py line~7192 — Apply shared-key bridging (or direct config read) so platforms.whatsapp.dm_policy: pairing from config.yaml reaches the adapter's config.extra, not just the .env variable.

  5. gateway/pairing.py — Fix approve matching logic so valid codes shown in hermes pairing list are found by hermes pairing approve. (Code bff982cd was visible in the list but approve returned "not found".)

  6. gateway/pairing.py — On revoke, clear the user's rate limit from _rate_limits.json so they can re-initiate pairing immediately.

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

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