fix(mcp): suppress unhandled rejection from async gateway event handler#100116
fix(mcp): suppress unhandled rejection from async gateway event handler#100116cxbAsDev wants to merge 2 commits into
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 5, 2026, 7:55 AM ET / 11:55 UTC. Summary PR surface: Source +15, Tests +50. Total +65 across 2 files. Reproducibility: yes. from source inspection rather than a local run. Current main passes an async MCP handler to a void GatewayClient callback, BaseGatewayClient only catches synchronous throws, and OpenClaw exits on ordinary unhandled rejections. Review metrics: none identified. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Land exactly one version of the MCP event containment fix; prefer this focused PR if maintainers accept scoped no-retry semantics, otherwise let #100258 supersede it after that batch merges. Do we have a high-confidence way to reproduce the issue? Yes, from source inspection rather than a local run. Current main passes an async MCP handler to a void GatewayClient callback, BaseGatewayClient only catches synchronous throws, and OpenClaw exits on ordinary unhandled rejections. Is this the best way to solve the issue? Yes. Catching at the MCP bridge boundary is the narrow maintainable fix because GatewayClient currently declares onEvent as void; a broader shared callback policy can be a separate maintainer-directed change. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 0fc29969d960. Label changesLabel justifications:
Evidence reviewedPR surface: Source +15, Tests +50. Total +65 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (9 earlier review cycles; latest 8 shown)
|
ProofBehaviorThe Source
onEvent: (event) => {
void this.handleGatewayEvent(event).catch(() => {});
},Test outputNotes
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
b298fef to
b1f2f6e
Compare
|
Rebased onto current What I did:
About the earlier
About the event-delivery semantics flagged by ClawSweeper:
Please let me know if anything else is needed to land this independently. |
b1f2f6e to
77bddb0
Compare
77bddb0 to
233dfe8
Compare
|
Thank you for the contribution. This fix landed with contributor co-authorship preserved in #100258 ( I consolidated the source fixes into a maintainer takeover because the contributor branches were based on rewritten pre- |
What Problem This Solves
The
onEventcallback inOpenClawChannelBridgecallsvoid this.handleGatewayEvent(event)without observing the returned promise. SincehandleGatewayEventis async and can reject, this creates an unhandled promise rejection that crashes the MCP gateway process.Why This Change Was Made
Contain the async handler rejection and emit a low-noise diagnostic, matching the existing notification-failure observability pattern in the same bridge (
src/mcp/channel-bridge.ts:399). Failed session or approval events are therefore visible to operators instead of disappearing silently.User Impact
Prevents the gateway from crashing when an MCP channel bridge event handler throws, while keeping failures observable.
Evidence
Behavior
The
onEventcallback now delegates todispatchGatewayEvent, which awaitshandleGatewayEventinside atry/catch. On rejection it writes exactly one stderr record (openclaw mcp: gateway event <type> failed), with the full error shown only when--verboseis on.Source
src/mcp/channel-bridge.ts:150src/mcp/channel-bridge.ts:524Unit test output
Real runtime proof
I ran a real OpenClaw MCP bridge against the local gateway (
ws://127.0.0.1:18789) and forcedhandleGatewayEventto reject forsession.messageevents. The bridge stayed alive and emitted the expected diagnostic on stderr:The injection was removed before committing; the committed code only logs real failures.
Regression coverage
a rejected gateway event still emits exactly one diagnostic record with verbose offa rejected gateway event includes error detail with verbose onBoth tests force
handleGatewayEventto reject, calldispatchGatewayEvent, and assert the exact stderr output shape while confirming the error detail is redacted unless verbose is enabled.