Skip to content
Latchkey

SSE "EventSource ... connection error" in CI tests

An EventSource fires its error event when it cannot open the stream or the connection drops. In tests this is usually the SSE endpoint being not ready, returning the wrong content type, or closing early.

What this error means

A test attaches es.onerror and it fires instead of onmessage. The stream never delivers events, often because the server was not listening or did not send text/event-stream.

SSE
EventSource failed: connection error
  es.onerror = (e) => { /* e.type === 'error' */ };
  // readyState becomes EventSource.CLOSED (2) after a fatal error

Common causes

The SSE server is not ready or returns a wrong content type

A not-yet-listening server, or an endpoint that returns application/json instead of text/event-stream, makes EventSource error instead of streaming.

The stream closed before events arrived

A server that ends the response early (or a proxy that buffers and cuts it) causes a connection error before the test sees a message.

How to fix it

Serve the correct SSE headers and wait for readiness

  1. Return Content-Type: text/event-stream and keep the response open.
  2. Ensure the server is listening before constructing the EventSource.
  3. Assert on onmessage, and treat onerror as a failure with the readyState logged.
server.mjs
res.writeHead(200, {
  'Content-Type': 'text/event-stream',
  'Cache-Control': 'no-cache',
  Connection: 'keep-alive',
});

Wait for open before asserting

Wait for the open event so the stream is established before the test expects messages.

test.mjs
await new Promise((res, rej) => { es.onopen = res; es.onerror = rej; });

How to prevent it

  • Return text/event-stream and keep the SSE response open.
  • Start the EventSource only after the server is listening.
  • Wait for the open event before asserting on messages.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →