fix: observe the derived promise so an unexpected rejection can't go unhandled

Review feedback (round 2). Narrowing the handler in the previous commit
fixed the silent-pass but reintroduced #1947's own failure class on the
unexpected path: `then` returns a *derived* promise, and the re-throw
rejects that one rather than `call`. The caller doesn't await it until
after `disconnect()`, so a rejection arriving while the test is still
waiting on progress notifications sits unobserved for seconds and Node
reports it as an unhandled rejection.

Attach an observer to the derived promise the moment it exists. Nothing is
swallowed — it stays rejected, so the caller's `await` still fails the test.

Verified both directions with a probe rejecting with a non-ConnectionClosed
error and awaiting after a 1.5s gap: without the observer the run reports
"Unhandled Rejection" + "Errors 1 error"; with it, the test fails and the
run stays clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDdo1rNRVQnVRRdsqSrvG3
This commit is contained in:
cliffhall 2026-08-10 18:09:52 -04:00
commit c60563b7d6

View file

@ -117,7 +117,7 @@ async function getTool(client: InspectorClient, name: string): Promise<Tool> {
* notifications it managed to emit first.
*/
function settleInFlight(call: Promise<unknown>): Promise<void> {
return call.then(
const settled = call.then(
() => undefined,
(error: unknown) => {
if (
@ -129,6 +129,15 @@ function settleInFlight(call: Promise<unknown>): Promise<void> {
throw error;
},
);
// `then` returns a *derived* promise, and the re-throw above rejects that one
// — not `call`. The caller does not await it until after `disconnect()`, so an
// unexpected rejection arriving while the test is still waiting on progress
// notifications would sit unobserved for seconds and be reported as an
// unhandled rejection: precisely the failure this helper exists to prevent.
// Observe it the moment it exists. This does not swallow anything — `settled`
// stays rejected, so the caller's `await` still fails the test.
settled.catch(() => undefined);
return settled;
}
/** Get all resources from the client via listResources() (paginates if needed). */