How to Resolve the Jest Error: "Exceeded timeout of 5000 ms" in JavaScript
The error message Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout is one of the most common issues when writing asynchronous tests in Jest. It means that your test started an async operation but did not finish within the default 5-second time limit.
This guide will explain the two main causes of this error: a test that is genuinely slow and a test that is written incorrectly. You will learn how to increase the timeout and, more importantly, how to correctly write async tests with async/await and the older done callback.
The Core Problem: Asynchronous Tests Taking Too Long
Jest is designed to run tests quickly. By default, if a single test takes longer than 5 seconds (5000 ms), Jest will automatically fail it with a timeout error. This prevents a broken test from hanging your entire test suite.
This error is most common when you are testing code that involves:
- Network requests (
fetch,axios) - Database queries
- Complex calculations
- Code that uses
setTimeoutorsetInterval
The following test simulates a long-running operation that takes 6 seconds. It will fail because it exceeds the default 5-second timeout.
// This test will fail by default
it('should resolve with the correct data', async () => {
const promise = new Promise(resolve => {
setTimeout(() => resolve('some data'), 6000); // Resolves after 6 seconds
});
const data = await promise;
expect(data).toBe('some data');
});
Error Output:
Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.
Solution 1: Increasing the Jest Timeout
If your test is expected to take longer than 5 seconds, the solution is to increase the timeout.
For a Single Test
You can provide a third argument to the test() (or it()) function, which is the timeout in milliseconds for that specific test.
Solution:
it('should resolve with the correct data', async () => {
const promise = new Promise(resolve => {
setTimeout(() => resolve('some data'), 6000);
});
const data = await promise;
expect(data).toBe('some data');
}, 10000); // 10,000 ms = 10 seconds timeout for this test
This is the best approach when only a few specific tests are slow.
For All Tests (Global Configuration)
If most of your tests are slow (e.g., in an end-to-end test suite), you can increase the timeout globally in your Jest configuration file.
jest.config.js:
module.exports = {
// The default timeout for all tests, in milliseconds.
testTimeout: 30000, // 30 seconds
};
This sets the new default for your entire project, so you don't have to specify it on each test.
Solution 2 (Common Mistake): Correctly Handling Async Test Logic
Often, a timeout error is not because the test is slow, but because Jest doesn't know when the test has finished. This happens when you mix up different styles of async test code.
Using async/await (Recommended)
This is the modern and best practice. When you mark the test function as async, Jest automatically waits for the promise returned by the function to resolve.
Solution:
it('should work with async/await', async () => {
const data = await someAsyncFunction();
expect(data).toBe('expected value');
});
Using the done Callback
This is an older pattern. If your test function accepts an argument (conventionally named done), Jest will wait until that done() callback is explicitly called before finishing the test.
Solution:
it('should work with a done callback', (done) => {
someAsyncFunction().then(data => {
expect(data).toBe('expected value');
done(); // You must call done() to signal completion
});
});
If you forget to call done(), the test will always time out.
The Pitfall: Mixing async/await with done
You cannot use both async/await and a done callback in the same test. Doing so will cause Jest to produce a timeout error because it doesn't know which signal to wait for.
Example of code with errors:
// INCORRECT: This test will always time out.
it('should not mix async and done', async (done) => {
const data = await someAsyncFunction();
expect(data).toBe('expected value');
done();
});
Solution: Choose one pattern and stick with it. For modern JavaScript, async/await is strongly preferred for its readability. Simply remove the done argument.
// CORRECTED: Remove the 'done' argument
it('should use only async/await', async () => {
const data = await someAsyncFunction();
expect(data).toBe('expected value');
});
Conclusion
The "Exceeded timeout" error in Jest almost always points to one of two issues:
- The test is legitimately slow: If an asynchronous operation is expected to take longer than 5 seconds, increase the timeout either for the specific
test(..., 10000)or globally injest.config.js. - The test is written incorrectly: If your test finishes quickly but still times out, ensure you are not accidentally mixing
async/awaitwith adonecallback. Remove thedoneargument when usingasync/await.
By diagnosing which of these two problems you have, you can quickly fix the timeout error and ensure your asynchronous tests run reliably.