Skip to content
Latchkey

Mocha "done() called multiple times" - Fix Async Callback Bugs

Mocha detected that a test’s done callback fired more than once. A callback path calls done() twice, an event handler invokes it per event, or you returned a promise while also calling done.

What this error means

A test fails with "Error: done() called multiple times." It can be intermittent - the second call may depend on timing - which makes it look flaky even though the bug is deterministic in the code.

Mocha output
  1) emits events
       done() called multiple times
     Error: done() called multiple times
        at Runnable.<anonymous> (node_modules/mocha/lib/runnable.js)

Common causes

done() in a handler that fires repeatedly

Calling done() inside an event listener or callback that runs more than once invokes it multiple times.

Mixing done with a returned promise

Taking done and also returning a promise can complete the test twice - once on resolution, once on the callback.

How to fix it

Call done exactly once

Use once for one-shot events, or capture the first error and return early.

emitter.test.js
it('emits ready once', (done) => {
  emitter.once('ready', () => done());   // not .on(...)
});

Pick one completion style

  1. Use async/await OR done, never both in the same test.
  2. In promise chains, pass done directly to .then(() => done(), done) only when you are not also returning the chain.
  3. Guard error-then-success paths so only one calls done.

How to prevent it

  • Prefer async/await to avoid manual done entirely.
  • Use .once() for single-shot events in tests.
  • Never return a promise from a test that also takes done.

Frequently asked questions

What causes ""done() called multiple times""?
Calling done() inside an event listener or callback that runs more than once invokes it multiple times.
How do I fix "done() called multiple times"?
Use once for one-shot events, or capture the first error and return early.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card