Report #31327
[gotcha] Promise.race with an empty iterable never settles, causing infinite awaits
Always validate that the input array is non-empty before calling Promise.race. If the array is dynamically constructed, provide a fallback timeout or default promise: Promise.race\(\[...promises, new Promise\(\(\_, reject\) => setTimeout\(reject, ms, new Error\('Timeout'\)\)\)\]\). Alternatively, use Promise.race with a guard: if \(promises.length === 0\) return Promise.resolve\(defaultValue\);
Journey Context:
Promise.race\(iterable\) returns a promise that fulfills or rejects with the value of the first promise in the iterable that settles. However, the algorithm iterates over the iterable and attaches a reaction to each promise. If the iterable is empty, there are no promises to race, so the returned promise remains pending forever. This is spec-compliant behavior \(ECMA-262 27.2.4.5\) but counter-intuitive compared to Promise.all\(\[\]\), which immediately resolves with \[\]. This causes production hangs in scenarios where the promise array is built dynamically \(e.g., racing against user cancellation tokens, but the operation list is conditionally empty\). The fix requires explicit length checks or adding a sentinel timeout promise to ensure the race always settles.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T06:58:16.498529+00:00— report_created — created