openclaw - ✅(Solved) Fix [Bug]: bonjour: registerUnhandledRejectionHandler not plumbed in; watchdog teardown crashes gateway [1 pull requests, 3 comments, 4 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#72481Fetched 2026-04-27 05:29:51
View on GitHub
Comments
3
Participants
4
Timeline
6
Reactions
0
Timeline (top)
commented ×3closed ×1cross-referenced ×1labeled ×1

@openclaw/bonjour already has the right defenses against ciao's "CIAO PROBING/ANNOUNCEMENT CANCELLED" unhandled rejections — but the handler is never installed, because registerUnhandledRejectionHandler is not passed into startGatewayBonjourAdvertiser. Result: the watchdog's own teardown path crashes the gateway.

Affected version: 2026.4.24. File: extensions/bonjour/index.js (and the extensions/bonjour/src/... sources it builds from).

Root Cause

The plugin defines handleCiaoUnhandledRejection at index.js:102 with the correct classification logic, and uses deps.registerUnhandledRejectionHandler at index.js:153 to install it — if that dep is provided. But the plugin entry at line 287 invokes startGatewayBonjourAdvertiser({...}, { logger: api.logger }) and never passes registerUnhandledRejectionHandler. So cleanupUnhandledRejection resolves to undefined, the handler is never installed, and ciao's teardown rejection escapes to the host's process-level handler which calls process.exit(1).

For comparison: extensions/telegram/probe-ChPXZhx2.js and extensions/whatsapp/monitor-BifLJ1dl.js import registerUnhandledRejectionHandler directly from openclaw/plugin-sdk/runtime-env and install handlers themselves.

Fix Action

Fix / Workaround

Verified locally — three watchdog teardowns post-patch produced zero unhandled rejections, zero stability bundles, gateway stayed up.

Verified locally — three watchdog teardowns post-patch produced zero unhandled rejections, zero stability bundles, gateway stayed up.

PR fix notes

PR #72588: fix(bonjour): raise STUCK_ANNOUNCING_MS from 8s to 20s to avoid false-positive teardowns

Description (problem / solution / changelog)

Summary

Raises the bonjour advertiser watchdog's stuck-announcing threshold from 8s to 20s to eliminate false-positive teardowns on healthy LAN networks where the mDNS announce phase legitimately takes 12-13s.

Background

Issue #72481 reported that the bonjour watchdog was tearing down the advertiser on every gateway restart, producing 'CIAO ANNOUNCEMENT CANCELLED' unhandled rejections that crashed the gateway.

The primary issue (unhandled-rejection handler not plumbed through) was already fixed in commit 63241bf1 (post 2026.4.24). However, the issue reporter noted a secondary problem: even with the rejection swallowed, the watchdog was still firing false-positive teardowns on every restart because STUCK_ANNOUNCING_MS = 8000 is shorter than ciao's typical announce phase on real-world LANs (~12-13s on Mac/iOS networks).

Fix

Raise the threshold to 20s. This:

  • ✅ Eliminates the false-positive teardown on healthy networks (announce typically completes in 12-13s, well under 20s)
  • ✅ Still catches genuinely stuck advertisers (announce that never completes)
  • ✅ No behavior change for advertisers that announce quickly (most cases)

Verification

The reporter empirically observed announce phases consistently taking 12-13s on a single Mac Mini host on a normal LAN — well under the new 20s threshold but well over the old 8s threshold. Three reproductions in 24h on 2026.4.24.

Refs

  • Closes secondary issue in #72481
  • Related: 63241bf1 fix(bonjour): suppress ciao cancellation across plugin runtime copies (primary fix)

Changed files

  • extensions/bonjour/src/advertiser.ts (modified, +6/-1)

Code Example

-import { isTruthyEnvValue } from "openclaw/plugin-sdk/runtime-env";
+import { isTruthyEnvValue, registerUnhandledRejectionHandler } from "openclaw/plugin-sdk/runtime-env";

---

-   }, { logger: api.logger })).stop };
+   }, { logger: api.logger, registerUnhandledRejectionHandler })).stop };

---

-import { isTruthyEnvValue } from "openclaw/plugin-sdk/runtime-env";
+import { isTruthyEnvValue, registerUnhandledRejectionHandler } from "openclaw/plugin-sdk/runtime-env";

---

-   }, { logger: api.logger })).stop };
+   }, { logger: api.logger, registerUnhandledRejectionHandler })).stop };

---
RAW_BUFFERClick to expand / collapse

Bug type

Crash (process/app exits or hangs)

Beta release blocker

No

Summary

Environment

  • OpenClaw version: 2026.4.24 (cbcfdf6)
  • Node: 22.22.0
  • OS: macOS Tahoe 26.x (Apple Silicon, ARM64)
  • Install method: npm install -g openclaw (Homebrew npm)

Summary

@openclaw/bonjour already has the right defenses against ciao's "CIAO PROBING/ANNOUNCEMENT CANCELLED" unhandled rejections — but the handler is never installed, because registerUnhandledRejectionHandler is not passed into startGatewayBonjourAdvertiser. Result: the watchdog's own teardown path crashes the gateway.

Affected version: 2026.4.24. File: extensions/bonjour/index.js (and the extensions/bonjour/src/... sources it builds from).

Suggested fix

Two changes to extensions/bonjour/index.js:

-import { isTruthyEnvValue } from "openclaw/plugin-sdk/runtime-env";
+import { isTruthyEnvValue, registerUnhandledRejectionHandler } from "openclaw/plugin-sdk/runtime-env";
-   }, { logger: api.logger })).stop };
+   }, { logger: api.logger, registerUnhandledRejectionHandler })).stop };

Verified locally — three watchdog teardowns post-patch produced zero unhandled rejections, zero stability bundles, gateway stayed up.

Secondary issue: STUCK_ANNOUNCING_MS = 8000 is too tight

Even with the rejection swallowed, the watchdog still tears down the advertiser on every restart in our environment (announce phase consistently takes 12–13s). Suggest raising the default to 2e4 (20s) — eliminates the false-positive teardown without weakening the stuck-state recovery.

Steps to reproduce

On a LAN with normal mDNS probe latency (~10–13s for the announce phase), the bonjour watchdog at line ~227 fires recreateAdvertiser(...) after STUCK_ANNOUNCING_MS = 8000. The teardown calls responder.shutdown() which cancels in-flight ciao promises, producing:

[plugins] bonjour: restarting advertiser (service stuck in announcing for 12925ms ...) [openclaw] Unhandled promise rejection: CIAO ANNOUNCEMENT CANCELLED [openclaw] wrote stability bundle: ~/.openclaw/logs/stability/openclaw-stability-...-unhandled_rejection.json

Process exits. Three reproductions in 24h on a single mac-mini host.

Root cause

The plugin defines handleCiaoUnhandledRejection at index.js:102 with the correct classification logic, and uses deps.registerUnhandledRejectionHandler at index.js:153 to install it — if that dep is provided. But the plugin entry at line 287 invokes startGatewayBonjourAdvertiser({...}, { logger: api.logger }) and never passes registerUnhandledRejectionHandler. So cleanupUnhandledRejection resolves to undefined, the handler is never installed, and ciao's teardown rejection escapes to the host's process-level handler which calls process.exit(1).

For comparison: extensions/telegram/probe-ChPXZhx2.js and extensions/whatsapp/monitor-BifLJ1dl.js import registerUnhandledRejectionHandler directly from openclaw/plugin-sdk/runtime-env and install handlers themselves.

Suggested fix

Two changes to extensions/bonjour/index.js:

-import { isTruthyEnvValue } from "openclaw/plugin-sdk/runtime-env";
+import { isTruthyEnvValue, registerUnhandledRejectionHandler } from "openclaw/plugin-sdk/runtime-env";
-   }, { logger: api.logger })).stop };
+   }, { logger: api.logger, registerUnhandledRejectionHandler })).stop };

Verified locally — three watchdog teardowns post-patch produced zero unhandled rejections, zero stability bundles, gateway stayed up.

Secondary issue: STUCK_ANNOUNCING_MS = 8000 is too tight

Even with the rejection swallowed, the watchdog still tears down the advertiser on every restart in our environment (announce phase consistently takes 12–13s). Suggest raising the default to 2e4 (20s) — eliminates the false-positive teardown without weakening the stuck-state recovery.

Expected behavior

The watchdog should be able to tear down and restart the advertiser without crashing the gateway. The plugin already contains the correct classification logic in handleCiaoUnhandledRejection — it just isn't wired up because registerUnhandledRejectionHandler isn't passed through to the entry point. Either the handler is installed (so cancellation rejections are swallowed by design), or the watchdog's teardown path doesn't produce them in the first place. Either outcome leaves the gateway running across watchdog-triggered restarts.

Actual behavior

The bonjour watchdog detects the mDNS advertiser stuck in the announcing phase (typical on LANs where ciao's announce takes 12–13s but STUCK_ANNOUNCING_MS = 8000), calls recreateAdvertiser(), which calls responder.shutdown(), which cancels in-flight ciao promises. Those produce "CIAO ANNOUNCEMENT CANCELLED" rejections. Because the bonjour plugin's unhandled-rejection handler is never installed (registerUnhandledRejectionHandler is not passed into startGatewayBonjourAdvertiser), the rejection escapes to the host process handler, a stability bundle is written, and the gateway exits with code 1. Reproduced three times in 24 hours on a single Mac Mini host running 2026.4.24.

OpenClaw version

2026.4.24 (cbcfdf6)

Operating system

OS: macOS Tahoe 26.x

Install method

npm install -g openclaw (Homebrew npm)

Model

claude-sonnet 4.6

Provider / routing chain

Not on a model request path. This bug is in the local mDNS service advertiser — the path is: bonjour plugin (extensions/bonjour) → ciao library → mDNS over UDP 5353 (LAN multicast) No HTTP gateway, no proxy, no LLM provider, no model router involved. The crash originates from a cancelled promise in ciao when the watchdog tears down the advertiser; LLM routing is unrelated.

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

extent analysis

TL;DR

The most likely fix is to pass registerUnhandledRejectionHandler to startGatewayBonjourAdvertiser in extensions/bonjour/index.js to prevent unhandled rejections from crashing the gateway.

Guidance

  • Update the import statement in extensions/bonjour/index.js to include registerUnhandledRejectionHandler from openclaw/plugin-sdk/runtime-env.
  • Pass registerUnhandledRejectionHandler to startGatewayBonjourAdvertiser to install the unhandled rejection handler.
  • Consider increasing the value of STUCK_ANNOUNCING_MS to reduce false-positive teardowns.
  • Verify the fix by checking for unhandled rejections and stability bundles after watchdog teardowns.

Example

-import { isTruthyEnvValue } from "openclaw/plugin-sdk/runtime-env";
+import { isTruthyEnvValue, registerUnhandledRejectionHandler } from "openclaw/plugin-sdk/runtime-env";

// ...

-   }, { logger: api.logger })).stop };
+   }, { logger: api.logger, registerUnhandledRejectionHandler })).stop };

Notes

The suggested fix assumes that the registerUnhandledRejectionHandler function is correctly implemented in openclaw/plugin-sdk/runtime-env. Additionally, increasing STUCK_ANNOUNCING_MS may not be necessary in all environments, and its optimal value may vary.

Recommendation

Apply the suggested fix by updating the import statement and passing registerUnhandledRejectionHandler to startGatewayBonjourAdvertiser, as this should prevent unhandled rejections from crashing the gateway.

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…

FAQ

Expected behavior

The watchdog should be able to tear down and restart the advertiser without crashing the gateway. The plugin already contains the correct classification logic in handleCiaoUnhandledRejection — it just isn't wired up because registerUnhandledRejectionHandler isn't passed through to the entry point. Either the handler is installed (so cancellation rejections are swallowed by design), or the watchdog's teardown path doesn't produce them in the first place. Either outcome leaves the gateway running across watchdog-triggered restarts.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: bonjour: registerUnhandledRejectionHandler not plumbed in; watchdog teardown crashes gateway [1 pull requests, 3 comments, 4 participants]