Skip to content

fix(mcp): suppress unhandled rejection from async gateway event handler#99895

Closed
cxbAsDev wants to merge 4 commits into
openclaw:mainfrom
cxbAsDev:fix/channel-bridge-void-async-catch
Closed

fix(mcp): suppress unhandled rejection from async gateway event handler#99895
cxbAsDev wants to merge 4 commits into
openclaw:mainfrom
cxbAsDev:fix/channel-bridge-void-async-catch

Conversation

@cxbAsDev

@cxbAsDev cxbAsDev commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Add .catch() with process.stderr.write diagnostic to the MCP channel bridge onEvent callback. The async handler can reject; previously the rejection caused an unhandled rejection crash. Now the error is logged for observability.

Real behavior proof (required for external PRs)

Behavior addressed: void this.handleGatewayEvent(event) in an event callback without .catch(). If the handler rejects, the unhandledRejection crashes the process.

Real environment tested: Linux, Node 22, OpenClaw main

Before-fix evidence: void this.handleGatewayEvent(event) — rejection → unhandledRejection → crash

After-fix evidence: void this.handleGatewayEvent(event).catch(...) with process.stderr.write — rejection → logged → no crash. Uses same stderr diagnostic pattern as line 401-404 in the same file.

What was not tested: Triggering an actual rejection in handleGatewayEvent.

Risk

Low. Error logged for observability instead of crashing.

🤖 Generated with Claude Code
Co-Authored-By: Claude [email protected]

The onEvent callback calls void this.handleGatewayEvent(event) without
.catch(). If the async handler rejects, the unhandled promise rejection
crashes the process. Add a noop catch handler.

Co-Authored-By: Claude <[email protected]>
@clawsweeper

clawsweeper Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 4, 2026, 5:41 AM ET / 09:41 UTC.

Summary
The PR adds a .catch() to the MCP channel bridge Gateway onEvent callback and writes a stderr diagnostic when handleGatewayEvent rejects.

PR surface: Source +2. Total +2 across 1 file.

Reproducibility: no. live high-confidence reproduction is posted. Source inspection shows the async handleGatewayEvent promise is dropped while the Gateway client only catches synchronous callback throws, but the PR body says an actual rejection was not triggered.

Review metrics: none identified.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted terminal output, logs, or a live validation transcript from a real MCP/Gateway run that forces a handler rejection and shows the new diagnostic without an unhandled rejection.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The PR body includes source reasoning but admits the actual rejection path was not exercised; add redacted terminal/log/live output that shows the after-fix diagnostic and no unhandled rejection. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] The crash-avoidance claim is still based on source reasoning and PR-body text; no posted real run triggers a handleGatewayEvent rejection and shows the new diagnostic plus no unhandled rejection.

Maintainer options:

  1. Decide the mitigation before merge
    Land the narrow bridge-boundary catch after after-fix proof shows an actual handler rejection is contained and logged; keep the GatewayClient callback contract unchanged unless maintainers want a broader async callback API.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] No automated repair is needed; the remaining blocker is contributor-supplied real behavior proof or a maintainer decision to accept source-level proof for this tiny MCP hardening patch.

Security
Cleared: The diff only adds local stderr error handling in an existing MCP bridge callback and does not change dependencies, workflows, permissions, secrets, or executable supply-chain inputs.

Review details

Best possible solution:

Land the narrow bridge-boundary catch after after-fix proof shows an actual handler rejection is contained and logged; keep the GatewayClient callback contract unchanged unless maintainers want a broader async callback API.

Do we have a high-confidence way to reproduce the issue?

No live high-confidence reproduction is posted. Source inspection shows the async handleGatewayEvent promise is dropped while the Gateway client only catches synchronous callback throws, but the PR body says an actual rejection was not triggered.

Is this the best way to solve the issue?

Yes, this is an acceptable narrow fix for the bridge-owned async handler boundary. A broader GatewayClient Promise-return contract is possible, but current production sibling callbacks keep async work contained locally and the public callback type is void.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against a0e604862470.

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The PR body includes source reasoning but admits the actual rejection path was not exercised; add redacted terminal/log/live output that shows the after-fix diagnostic and no unhandled rejection. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Label justifications:

  • P2: This is a focused MCP process availability hardening fix with limited blast radius and no evidence of a live release-blocking outage.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The PR body includes source reasoning but admits the actual rejection path was not exercised; add redacted terminal/log/live output that shows the after-fix diagnostic and no unhandled rejection. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +2. Total +2 across 1 file.

View PR surface stats
Area Files Added Removed Net
Source 1 3 1 +2
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 1 3 1 +2

What I checked:

  • Current main callback drops the promise: Current main wires onEvent to void this.handleGatewayEvent(event), so any rejected promise from the async handler is not observed at this boundary. (src/mcp/channel-bridge.ts:150, a0e604862470)
  • Gateway client only contains synchronous callback throws: The reusable Gateway client invokes this.opts.onEvent?.(evt) inside a try/catch, which catches thrown exceptions but does not await or attach a rejection handler to returned promises. (packages/gateway-client/src/client.ts:1449, a0e604862470)
  • Unhandled rejections are process-fatal by default: The global unhandled rejection handler logs an unhandled promise rejection and exits through terminal restore, so an uncaught handler rejection is availability-sensitive. (src/infra/unhandled-rejections.ts:540, a0e604862470)
  • PR diff keeps the fix local to the MCP bridge: The patch changes only src/mcp/channel-bridge.ts, adding a rejection handler that writes openclaw mcp: gateway event handler failed to stderr. (src/mcp/channel-bridge.ts:150, 8cde59038eb3)
  • Existing adjacent test coverage does not exercise this callback rejection: channel-bridge.test.ts exposes and calls handleGatewayEvent directly for bridge behavior, but the inspected tests do not cover the Gateway onEvent fire-and-forget rejection path introduced by this PR. (src/mcp/channel-bridge.test.ts:33, a0e604862470)
  • Real behavior proof remains incomplete: The PR body says Linux/Node 22 was used, but also states that triggering an actual rejection in handleGatewayEvent was not tested; the proof check only verified that the PR body includes context and evidence text. (8cde59038eb3)

Likely related people:

  • hansraj316: Authored the merged channel-bridge notification failure logging change that established the nearby stderr observability pattern this PR references. (role: adjacent behavior contributor; confidence: high; commits: 5d6899c7317e; files: src/mcp/channel-bridge.ts, src/mcp/channel-bridge.test.ts)
  • vincentkoc: Recently touched both the MCP channel bridge request limits and Gateway callback containment behavior, which are adjacent to this event-handler failure boundary. (role: recent gateway and MCP runtime contributor; confidence: high; commits: a39e548ede22, 09427aa76091; files: src/mcp/channel-bridge.ts, packages/gateway-client/src/client.ts)
  • Feelw00: Authored the merged pending approval bounds work in src/mcp/channel-bridge.ts, including tests around handleGatewayEvent state handling. (role: channel bridge state contributor; confidence: medium; commits: c6b1fede5a2b; files: src/mcp/channel-bridge.ts, src/mcp/channel-bridge.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (6 earlier review cycles)
  • reviewed 2026-07-04T08:44:20.551Z sha 160447c :: needs real behavior proof before merge. :: [P2] Keep gateway event failures observable
  • reviewed 2026-07-04T08:51:50.072Z sha 160447c :: needs real behavior proof before merge. :: [P2] Keep gateway event failures observable
  • reviewed 2026-07-04T09:04:10.828Z sha 604ea48 :: needs real behavior proof before merge. :: [P2] Keep gateway event failures observable
  • reviewed 2026-07-04T09:09:22.441Z sha 604ea48 :: needs real behavior proof before merge. :: [P2] Keep gateway event failures observable
  • reviewed 2026-07-04T09:25:44.117Z sha 28d7530 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-04T09:30:42.304Z sha 28d7530 :: needs real behavior proof before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jul 4, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 4, 2026
@cxbAsDev cxbAsDev closed this Jul 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal backlog priority with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant