Skip to content

fix(health-check): prevent unhandled rejection on timeout#1756

Merged
piorpua merged 1 commit intomainfrom
fix/sentry-ELECTRON-P
Mar 26, 2026
Merged

fix(health-check): prevent unhandled rejection on timeout#1756
piorpua merged 1 commit intomainfrom
fix/sentry-ELECTRON-P

Conversation

@kaizhou-lab
Copy link
Copy Markdown
Collaborator

Summary

  • Add responsePromise.catch(() => {}) to prevent unhandled rejection when health check timeout fires while sendMessage.invoke() is still pending
  • The actual timeout error is still caught by the outer try-catch via await responsePromise

Sentry: ELECTRON-P (105 occurrences)

Closes #1755

Test plan

  • Unit test: rejected promise with .catch() attached does not trigger unhandledRejection
  • Unit test: normal resolve still works with .catch() attached
  • Type check passes
  • Lint passes

…ing sendMessage

The health check responsePromise could reject (via setTimeout) while
sendMessage.invoke() was still pending. Since responsePromise wasn't
yet being awaited, this produced an unhandled promise rejection.

Add responsePromise.catch(() => {}) immediately after creation to mark
the rejection as handled. The actual error is still caught by the outer
try-catch via `await responsePromise`.

Fixes ELECTRON-P
@kaizhou-lab kaizhou-lab marked this pull request as ready for review March 26, 2026 12:30
@piorpua piorpua added the bot:reviewing Review in progress (mutex) label Mar 26, 2026
@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 26, 2026

Code Review:fix(health-check): prevent unhandled rejection on timeout (#1756)

变更概述

本 PR 修复 Sentry 高频错误 ELECTRON-P(105 次),根因是健康检查中 responsePromisesendMessage.invoke() 仍在 pending 时由超时 timer 触发拒绝,此时该 promise 尚未被 await,导致 Node.js 触发 unhandledRejection。修复方式为在 responsePromise 创建后立即附加 .catch(() => {}) 以标记拒绝为已处理,实际错误仍由外层 try-catch 通过 await responsePromise 捕获。同时新增了 tests/unit/healthCheckTimeout.test.ts 验证该模式的正确性。


方案评估

结论:✅ 方案合理

.catch(() => {}) 是 JavaScript 中防止 unhandled rejection 的标准惯用法,在创建 Promise 后立即挂载一个空 rejection handler,让 V8/Node 认为该拒绝已被消费,外层 await 仍能正常传播异常。方案最小化、侵入性低,与现有错误处理架构完全一致,无需引入额外抽象。


问题清单

未发现阻塞性问题。以下为一个低优先级观察:

🔵 LOW — 测试中 process.on('unhandledRejection', ...) 在 Vitest 环境下可靠性存疑

文件tests/unit/healthCheckTimeout.test.ts,第 22 行

问题代码

process.on('unhandledRejection', unhandledHandler);

问题说明:Vitest 在 Node 环境下会全局拦截 unhandledRejection 事件并将其转化为测试失败;测试自身再监听同一事件,执行顺序依赖 listener 注册顺序,存在环境耦合。若 Vitest 配置或版本变更(如开启 pool: 'forks'),该测试可能出现假阳性或假阴性。

当前 CI 全部通过,说明在现有配置下行为符合预期,不阻塞合并。建议后续将该测试替换为纯粹验证 .catch() 链式返回行为(promise 二次 await 仍能收到 rejection)的逻辑断言,避免依赖进程级副作用。


汇总

# 严重级别 文件 问题
1 🔵 LOW tests/unit/healthCheckTimeout.test.ts:22 process.on('unhandledRejection') 在 Vitest 环境可靠性存疑

结论

批准合并 — 修复方案正确、最小化,测试覆盖核心场景,CI 全部通过,无阻塞性问题。


本报告由本地 pr-review skill 生成,包含完整项目上下文,无截断限制。

@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 26, 2026

✅ 已自动 review,无阻塞性问题,正在触发自动合并。

@piorpua piorpua added bot:done Auto-merged by bot and removed bot:reviewing Review in progress (mutex) labels Mar 26, 2026
@piorpua piorpua merged commit a03bb45 into main Mar 26, 2026
17 checks passed
@piorpua piorpua deleted the fix/sentry-ELECTRON-P branch March 26, 2026 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:done Auto-merged by bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: health check timeout causes unhandled promise rejection

2 participants