A batch worker using `Promise.allSettled` then discarding the result. Half the items error out; nobody sees it. Mesrai flagged the misuse.
The vulnerable diff
// workers/batch.ts
async function batchProcess(items: Item[]) {
// BUG: allSettled doesn't throw — result must be inspected
await Promise.allSettled(items.map(item => processItem(item)));
}What is wrong
`Promise.allSettled` is useful when you want to wait for every promise regardless of success/failure — unlike `Promise.all` which rejects on the first failure. But `allSettled` returns an array of `{ status, value | reason }`; the caller has to inspect it. Awaiting and discarding the result is functionally equivalent to writing a catch-all that swallows every rejection.
The attack
Symptom:
batchProcess(items) called with 200 items.
50 of them error out (network blip, validation, etc).
The await resolves cleanly.
No logs, no metric, no signal.
Operator sees: 'batch complete'.Subtle: looks like the right tool, used the wrong way.
Mesrai's review comment
mesraipilot · Bot · reviewed 1 min ago
[mesrai] [code-review] [Logic] [AllSettled-Misuse] [medium]
Promise.allSettled without inspecting the result swallows every
rejection. Inspect + decide:
const results = await Promise.allSettled(
items.map(item => processItem(item))
);
const failures = results
.map((r, i) => ({ r, item: items[i] }))
.filter(({ r }) => r.status === "rejected");
if (failures.length > 0) {
log.warn({ failed: failures.length, total: items.length }, "batch had failures");
metrics.increment("batch.failed", failures.length);
// optional: throw if you want batch-level failure
}
If you don't actually need the all-settled semantics (you want fail-
fast), use Promise.all so errors propagate.The fix
// workers/batch.ts — fixed
async function batchProcess(items: Item[]) {
const results = await Promise.allSettled(
items.map(item => processItem(item))
);
const failures = results
.map((r, i) => ({ r, item: items[i] }))
.filter(({ r }) => r.status === "rejected");
if (failures.length > 0) {
log.warn({ failed: failures.length, total: items.length, samples: failures.slice(0, 3) },
"batch had failures");
metrics.increment("batch.failed", failures.length);
}
}Inspect the result, log failures, emit metric. Optional throw if batch-level failure should propagate.
Why human review missed it
Promise.allSettled is right for fault-tolerant batch work but the result must be consumed. Mesrai catches every `await Promise.allSettled` whose result is discarded.
Related rules + further reading
Mesrai rule pack: logic/all-settled-must-inspect — flags Promise.allSettled with discarded result.
MDN: Promise.allSettled — return value shape.
Common in batch workers that started as Promise.all and got switched.
Takeaway
allSettled returns; caller must inspect. Otherwise rejections vanish. Mesrai catches every discarded result.