Mocha "Timeout of 2000ms exceeded ... ensure done() is called"
By Kaveh Alemi·Latchkey
A Mocha test exceeded the default 2000 ms timeout. The async test never called done(), never returned its promise, or genuinely took longer than the limit on a loaded runner.
What this error means
A test fails with "Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure \"done()\" is called; if returning a Promise, ensure it resolves." It often surfaces only in slower CI.
mocha
1) GET /users
returns 200:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure
"done()" is called; if returning a Promise, ensure it resolves.
Common causes
done() never called or promise not returned
A test takes the done callback but never calls it (an error path skips it), or it does async work without returning the promise, so Mocha waits to the timeout.
Work slower than 2000 ms
A real HTTP or DB round-trip legitimately exceeds the default 2s, especially under CI load.
How to fix it
Return the promise (drop done)
Returning a promise - or using async/await - lets Mocha track completion without a callback you might forget.
it('slow', async function () {
this.timeout(10000);
/* ... */
});
// or via CLI: mocha --timeout 10000
How to prevent it
Prefer async/await or returned promises over done.
Set a realistic --timeout for integration suites.
Avoid arrow functions when you need this.timeout().
Frequently asked questions
What causes ""Timeout of 2000ms exceeded""?
A test takes the done callback but never calls it (an error path skips it), or it does async work without returning the promise, so Mocha waits to the timeout.
How do I fix "Timeout of 2000ms exceeded"?
Returning a promise - or using async/await - lets Mocha track completion without a callback you might forget.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.