Vitest "Failed to terminate worker" in CI
Vitest finished the tests but a pool worker would not stop, so it had to force-terminate the thread. The cause is an open handle the test never closed: a timer, an interval, a socket, or a promise that never resolves.
What this error means
Vitest prints "Failed to terminate worker while running ..." or "Terminating worker thread", and the run may hang or be flaky in CI. It often points at a specific test file that leaks a handle.
Error: Failed to terminate worker while running
/home/runner/work/app/src/queue.test.ts.
Tests closed successfully but something prevented the main process from exiting.Common causes
A timer or interval was never cleared
The test starts setInterval or setTimeout and never clears it, so the worker has pending work and cannot exit.
An open socket or unsettled promise
A database connection, server, or fetch was opened but never closed, keeping the event loop alive in the worker.
How to fix it
Close handles in teardown
- Clear timers and intervals the test created.
- Close sockets, servers, and connections in
afterEach/afterAll. - Re-run so the worker exits without being force-terminated.
afterEach(() => {
clearInterval(timer);
});
afterAll(async () => {
await server.close();
});Isolate to surface the leaking file
Run the suspected file alone with the forks pool to confirm which test leaks the handle.
npx vitest run src/queue.test.ts --pool=forksHow to prevent it
- Close every connection, server, and timer a test opens.
- Use
afterEach/afterAllto release resources deterministically. - Mock long-lived I/O so tests do not leak real handles.