jest open handles keeping process alive: how to find
Shows how to find open handles that keep a jest process from exiting. Use it when jest hangs after tests pass or CI jobs time out at teardown. Not for test failures, flaky assertions, or general jest slowness.
TL;DR
Run jest with --detectOpenHandles to get a report of what is keeping the event loop alive: usually a database connection, an HTTP server, a timer, or a socket that was never closed. The fix is almost always to close the resource in an afterAll hook (or use server.close() / client.disconnect() / clearInterval where it was created). Do not reach for --forceExit as the real fix; it masks leaks that will bite you in CI.
The query
jest open handles keeping process alive: how to findUse this when
- Jest prints test results but the process never exits
- CI jobs hang or time out after all tests pass
- You see "Jest did not exit" warnings in output
- You suspect leaked timers, servers, or DB connections
Not for
- Tests that fail with assertion errors
- Slow tests that still exit cleanly
- Memory leaks during the test run itself
Steps
- Re-run with
npx jest --detectOpenHandlesand read the reported handles and their creation stacks. Expected output: jest prints each open handle with a stack trace pointing at where it was created. - Map each handle to its owner: DB clients,
http.createServerwithoutclose(),setIntervalwithoutclearInterval, websocket or redis clients left connected. Expected output: a list of 1-3 resources tied to specific test files or setup modules. - Close each resource in an
afterAllhook in the file (or setup file) that created it, e.g.await db.disconnect()orserver.close(). Expected output: the resource is released when the test file finishes. - Re-run without
--detectOpenHandlesand confirm jest exits on its own within a few seconds of the results. Expected output: process exits cleanly, exit code 0, no "did not exit" warning.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst-x9E7gWYzGKN5Z9WABfIw
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.