Skip to content
Latchkey

OpenTelemetry JS SpanProcessor shutdown timeout hangs the test process in CI

A BatchSpanProcessor holds a live exporter connection and a scheduled flush timer. If the SDK is never shut down (or shutdown blocks trying to reach a dead collector), the Node event loop stays alive and the test runner hangs or times out.

What this error means

Jest reports "A worker process has failed to exit gracefully" or "did not exit one second after the test run completed", or the CI step hangs until the job timeout even though all tests passed.

node
Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't stopped
in your tests. Consider running Jest with --detectOpenHandles to troubleshoot.

Common causes

The SDK is never shut down after tests

BatchSpanProcessor schedules timers and keeps sockets open. Without calling sdk.shutdown() in an afterAll hook, those handles keep the process alive.

shutdown() blocks flushing to a dead collector

On shutdown the processor tries to flush queued spans to the OTLP endpoint. If nothing listens there, the flush waits out its export timeout, delaying or hanging exit.

How to fix it

Shut the SDK down in teardown

  1. Call await sdk.shutdown() in a global afterAll / teardown.
  2. Keep the export timeout short so a dead endpoint does not stall shutdown.
  3. For pure unit tests, disable the SDK so no processor starts.
test/setup.js
afterAll(async () => {
  await sdk.shutdown();   // flush + close exporter handles
});

Use SimpleSpanProcessor + InMemory exporter in tests

An in-memory exporter has no network handle to leave open, so the process exits cleanly.

test/setup.js
const exporter = new InMemorySpanExporter();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

How to prevent it

  • Always call sdk.shutdown() in test teardown.
  • Use InMemorySpanExporter for tests to avoid open sockets.
  • Set a short export/shutdown timeout so flush cannot block exit.

Frequently asked questions

What causes "SpanProcessor shutdown hangs"?
BatchSpanProcessor schedules timers and keeps sockets open. Without calling sdk.shutdown() in an afterAll hook, those handles keep the process alive.
How do I fix SpanProcessor shutdown hangs?
Shut the SDK down in teardown

Related guides

References

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