mocha done() called multiple times: how to fix
Fixes Mocha 'done() called multiple times' from double callbacks. Use when async Mocha tests call done twice. Not for promise-based tests (different pattern).
TL;DR
Something invoked the completion callback twice: an event firing twice, or both a promise resolving and done() being called. Pick one completion style per test and guard the other path.
Error
Error: done() called multiple times in test ["saves the record"]Steps
- Find the test and list every path that calls
done()or resolves. Expected: two paths visible. - Common case: both
.then(() => done())and adone()in the callback. Remove one. Expected: single completion. - If an event emitter fires twice, guard:
let called = false; ... if (!called) { called = true; done(); }. Expected: idempotent completion. - Prefer returning the promise instead of
done()for promise tests. Expected: Mocha handles completion; no double-call possible. - Re-run. Expected: green.
When to use
- The exact error
done() called multiple times. - Callback-style async tests.
When not to use
- Promise-returning tests (return the promise; drop done()).
- Async/await tests (no done() at all).
Tool compatibility
- Mocha 9 through 11.
Variant phrasings
Mocha done called twice
Same error; two completion paths.
done() invoked multiple times with async
Mixing styles; pick one.
Why it happens
Mocha counts completions. Callbacks, events, and promises each offer a completion path, and using two fires twice.
Edge cases
donepassed into a helper that also returns a promise is the classic trap.- Timeouts can fire
doneafter the test already completed; clear timers. - Prefer async/await for new tests;
done()is legacy.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_7tChTzyxPWpgIPNKK-X91Q
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.