openclaw - ✅(Solved) Fix BlueBubbles webhook POST returns 404 despite plugin reporting 'webhook listening' [1 pull requests, 6 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#49395Fetched 2026-04-08 00:55:37
View on GitHub
Comments
6
Participants
5
Timeline
11
Reactions
0
Timeline (top)
commented ×6subscribed ×2cross-referenced ×1marked_as_duplicate ×1

Fix Action

Fixed

PR fix notes

PR #49526: Gateway: rebind plugin registry before channel lifecycle

Description (problem / solution / changelog)

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: changing channels.bluebubbles.* could hot-reload the BlueBubbles channel after plugin runtime state had drifted, so the restart path could lose the live webhook registration and BlueBubbles webhook deliveries would fall through to 404 Not Found.
  • Why it matters: BlueBubbles could log that its webhook was listening, while http://localhost:18789/bluebubbles-webhook?... still behaved as if the route was missing after channel restart / hot reload.
  • What changed: gateway channel lifecycle calls now resolve and rebind the current channel-lifecycle plugin runtime state before start/stop/logout work, and config schema reads use snapshot plugin registries instead of mutating the live registry/hook-runner state.
  • What did NOT change (scope boundary): this does not change BlueBubbles webhook URLs, passwords, payload parsing, or webhook auth semantics.

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

  • Fixes #48624
  • Fixes #48734
  • Fixes #49395

User-visible / Behavior Changes

In the verified local BlueBubbles hot-reload path, the webhook stays reachable after a channels.bluebubbles.* config change and channel restart instead of falling through to 404 Not Found.

Security Impact (required)

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

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local gateway build / restart
  • Model/provider: N/A
  • Integration/channel (if any): BlueBubbles
  • Relevant config (redacted): channels.bluebubbles.* with a local webhook URL at http://localhost:18789/bluebubbles-webhook?...

Steps

  1. Start the local gateway with BlueBubbles configured.
  2. Change channels.bluebubbles.* in the local config so the BlueBubbles channel hot-reloads / restarts.
  3. Replay a webhook request to the existing BlueBubbles webhook URL.

Expected

  • The webhook route remains reachable after the config-triggered BlueBubbles restart, so the request reaches the BlueBubbles webhook handler.

Actual

  • Before this fix, the same replay could return 404 Not Found after channel restart / hot reload.

Evidence

Attach at least one:

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

Manual replay evidence from the current local verification:

  • Config edit triggered: config change detected; evaluating reload (channels.bluebubbles.allowFrom, channels.bluebubbles.accounts.default.allowFrom)
  • Gateway restart path triggered: restarting bluebubbles channel
  • BlueBubbles re-registered: BlueBubbles webhook listening on /bluebubbles-webhook
  • Replay result after hot reload: 400 invalid payload

That 400 invalid payload is intentional from an incomplete test payload and shows the request now reaches the BlueBubbles webhook handler instead of missing the route.

Human Verification (required)

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

  • Verified scenarios: on a local macOS gateway run, edited channels.bluebubbles.allowFrom / channels.bluebubbles.accounts.default.allowFrom, observed the config watcher trigger a BlueBubbles restart, and replayed the same webhook URL after restart.
  • Edge cases checked: the replay after hot reload returned 400 invalid payload instead of 404 Not Found, confirming handler reachability after the config-triggered restart.
  • What you did not verify: a full end-to-end live BlueBubbles conversation round-trip from a real inbound message through final OpenClaw reply delivery.

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/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert this PR.
  • Files/config to restore: src/gateway/server-channels.ts, src/gateway/server-plugin-runtime-state.ts, src/gateway/server.impl.ts, src/gateway/server-methods/config.ts, src/channels/plugins/index.ts, src/channels/plugins/registry.ts, src/gateway/server-channels.test.ts, src/gateway/server.config-patch.test.ts
  • Known bad symptoms reviewers should watch for: missing or duplicated plugin HTTP routes during channel restart / hot reload, or config schema reads mutating live plugin runtime state.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: channel lifecycle runtime rebinding now tracks more live plugin runtime state than the original narrow fix, so unsupported plugin runtime mutation paths may still surface edge cases outside the BlueBubbles repro.
    • Mitigation: regression coverage now covers stale-registry startup, same-channel live registry upgrades, and snapshot-only config schema loads; manual verification also confirms the local BlueBubbles hot-reload path no longer returns 404.

Changed files

  • src/channels/plugins/index.ts (modified, +6/-1)
  • src/channels/plugins/registry.ts (modified, +17/-10)
  • src/gateway/server-channels.test.ts (modified, +307/-13)
  • src/gateway/server-channels.ts (modified, +32/-2)
  • src/gateway/server-methods/config.ts (modified, +6/-3)
  • src/gateway/server-plugin-runtime-state.ts (added, +42/-0)
  • src/gateway/server.config-patch.test.ts (modified, +123/-0)
  • src/gateway/server.impl.ts (modified, +26/-0)

Code Example

channels: {
  bluebubbles: {
    enabled: true,
    serverUrl: "http://192.168.68.64:1234",
    password: "<redacted>",
    webhookPath: "/bluebubbles-webhook",
    dmPolicy: "pairing",
    groupPolicy: "allowlist",
  }
}
gateway: {
  port: 18789,
  mode: "local",
  bind: "loopback",
}

---

[bluebubbles] [default] starting provider (webhook=/bluebubbles-webhook)
[bluebubbles] [default] BlueBubbles server macOS 26.4.0
[bluebubbles] [default] BlueBubbles Private API enabled
[bluebubbles] [default] BlueBubbles webhook listening on /bluebubbles-webhook

---

$ curl -X POST http://127.0.0.1:18789/bluebubbles-webhook?password=<pw> -H "Content-Type: application/json" -d '{"type":"test"}'
Not Found (404)

$ curl http://127.0.0.1:18789/bluebubbles-webhook?password=<pw>
<!doctype html>... (SPA HTML - not the webhook handler)
RAW_BUFFERClick to expand / collapse

BlueBubbles webhook POST returns 404 despite plugin reporting "webhook listening"

Version: OpenClaw 2026.3.13 (61d171a) OS: macOS Tahoe 26.4.0 (arm64) BlueBubbles Server: 1.9.9

Problem

POST requests to the BlueBubbles webhook path return 404, while GET returns 200 (SPA catch-all HTML).

Config

channels: {
  bluebubbles: {
    enabled: true,
    serverUrl: "http://192.168.68.64:1234",
    password: "<redacted>",
    webhookPath: "/bluebubbles-webhook",
    dmPolicy: "pairing",
    groupPolicy: "allowlist",
  }
}
gateway: {
  port: 18789,
  mode: "local",
  bind: "loopback",
}

Evidence

Gateway startup log shows:

[bluebubbles] [default] starting provider (webhook=/bluebubbles-webhook)
[bluebubbles] [default] BlueBubbles server macOS 26.4.0
[bluebubbles] [default] BlueBubbles Private API enabled
[bluebubbles] [default] BlueBubbles webhook listening on /bluebubbles-webhook

But:

$ curl -X POST http://127.0.0.1:18789/bluebubbles-webhook?password=<pw> -H "Content-Type: application/json" -d '{"type":"test"}'
Not Found (404)

$ curl http://127.0.0.1:18789/bluebubbles-webhook?password=<pw>
<!doctype html>... (SPA HTML - not the webhook handler)

Notes

  • Outbound messaging (send via REST API) works fine
  • This was previously working (outbound messages were sent at 4:43 PM on 3/16)
  • Multiple gateway restarts (SIGUSR1 + full manual restart) don't fix it
  • No config changes were made between working and broken states
  • Plugin plugin entry is enabled in plugins.entries.bluebubbles

extent analysis

Fix Plan

The issue seems to be related to the BlueBubbles webhook configuration. To fix this, we need to ensure that the webhook path is correctly registered and handled by the gateway.

Step-by-Step Solution

  1. Verify Webhook Registration: Check the gateway code to ensure that the BlueBubbles webhook is registered correctly. The registration should include the webhook path and the handler function.
  2. Check Webhook Handler: Verify that the webhook handler function is correctly defined and handles POST requests. The handler function should parse the request body and process the incoming data.
  3. Update Webhook Configuration: Update the webhookPath configuration to include the leading slash if it's not already included.

Example code snippet to register the webhook:

// Register the BlueBubbles webhook
app.post('/bluebubbles-webhook', (req, res) => {
  // Handle the incoming request
  const requestBody = req.body;
  // Process the request body
  res.status(200).send('Webhook received');
});

In the config.json5 file, ensure that the webhookPath is correctly configured:

channels: {
  bluebubbles: {
    enabled: true,
    serverUrl: "http://192.168.68.64:1234",
    password: "<redacted>",
    webhookPath: "/bluebubbles-webhook", // Ensure the leading slash is included
    dmPolicy: "pairing",
    groupPolicy: "allowlist",
  }
}

Verification

To verify that the fix worked, send a POST request to the BlueBubbles webhook using curl:

curl -X POST http://127.0.0.1:18789/bluebubbles-webhook?password=<pw> -H "Content-Type: application/json" -d '{"type":"test"}'

If the fix is successful, the response should be 200 OK with the message Webhook received.

Extra Tips

  • Ensure that the gateway is restarted after making any configuration changes.
  • Verify that the BlueBubbles plugin is enabled and configured correctly.
  • Check the gateway logs for any errors or warnings related to the BlueBubbles webhook.

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