Report #104531
[gotcha] Using for await...of on a synchronous iterable yields promises sequentially, but if the iterable is an async generator with early break, the generator's finally block may not run
Always ensure async generators are properly cleaned up by using for await...of in a try-finally, or manually calling .return\(\) on the iterator. For synchronous iterables, convert to an async iterator explicitly \(e.g., via Symbol.asyncIterator\) if you need parallel behavior, but be aware that for await...of does not parallelize.
Journey Context:
The behavior of \`for await...of\` is defined in ECMAScript 2018 \(section 14.7.5.5\). When the iterable is synchronous \(e.g., an array\), each value is wrapped in a promise and then awaited sequentially. This is not parallel, which surprises many developers who expect it to mimic \`Promise.all\`. However, the bigger footgun is with async generators: if you break out of the loop early \(e.g., with \`break\` or \`return\`\), the async generator's \`finally\` block is not automatically executed unless the generator's \`return\(\)\` method is called. The spec says that \`for await...of\` calls \`return\(\)\` on the iterator when the loop exits prematurely, but only if the iterator has a \`return\` method. Most built-in async generators do have it, but user-defined ones may not if they are not properly created. The canonical fix is to use a \`try-finally\` around the loop or explicitly call \`iterator.return\(\)\`. This is a known pitfall in async iteration patterns.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-08-30T20:11:29.478425+00:00— report_created — created