Skip to content

fix: add .catch() guards to unguarded fire-and-forget promises#747

Open
buihongduc132 wants to merge 1 commit into
backnotprop:mainfrom
buihongduc132:upstream/fix-unguarded-promises
Open

fix: add .catch() guards to unguarded fire-and-forget promises#747
buihongduc132 wants to merge 1 commit into
backnotprop:mainfrom
buihongduc132:upstream/fix-unguarded-promises

Conversation

@buihongduc132
Copy link
Copy Markdown

What

Two places where .then() was called without .catch() on fire-and-forget promises, risking unhandled rejections that could crash the host process.

Why

When a promise is fired and forgotten (not awaited or returned), any rejection becomes an unhandled promise rejection. In Node.js/Bun, these can terminate the process or trigger warning spam.

Changes

1. packages/server/review.ts

detectRemoteDefaultCompareTarget() is called as a non-blocking best-effort check to auto-detect the remote default branch. If git fails (no git installed, invalid cwd, network timeout), the rejection was unhandled.

Fix: Add .catch() that swallows the error — the detection is purely cosmetic and the server should keep running fine without it.

2. packages/ai/providers/pi-sdk.ts

proc.exited fires when the Pi process dies. The .then() callback cleans up pending requests and notifies listeners. But if the process exits abnormally, the promise itself rejects — and since no one catches it, it becomes an unhandled rejection.

Fix: Add .catch() that swallows it. The cleanup already ran in .then().

Not changed

Integration saves (Obsidian/Bear/Octarine) use Promise.allSettled() which already handles rejections — no fix needed there.

Testing

  • 3 new tests in unguarded-promise.test.ts covering the error paths
  • Existing tests unaffected

Scope

~5 LOC of actual fixes (just .catch() additions). Zero behavior change for happy paths.

Two places where .then() was called without .catch() on fire-and-forget
promises, risking unhandled rejections:

1. review.ts: detectRemoteDefaultCompareTarget() is called as a
   non-blocking best-effort check. If git fails or cwd is invalid,
   the rejection would bubble up as unhandled.

2. pi-sdk.ts: proc.exited callback cleans up state but if the
   process exits abnormally the promise can reject. The callback
   already ran in .then(), so .catch() just swallows the rejection.

Integration saves (obsidian/bear/octarine) are NOT affected — they
use Promise.allSettled() which already handles rejections.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant