Skip to content
Latchkey

Socket.IO "Error: xhr poll error" in CI tests

Socket.IO opens its first connection over HTTP long-polling. "xhr poll error" is emitted on connect_error when that initial poll request fails, so the transport never upgrades and the test client never connects.

What this error means

A test fails when the client emits connect_error with err.message === "xhr poll error". It reproduces intermittently: the server sometimes has not finished binding its port when the client dials.

Socket.IO
Error: xhr poll error
    at XHR.onError (node_modules/engine.io-client/build/cjs/transport.js:...)
    at Request.<anonymous> (node_modules/engine.io-client/build/cjs/transports/polling-xhr.js:...)

Common causes

The test server is not listening yet

The client io(url) runs before httpServer.listen(...) has bound the port, so the polling request is refused and Socket.IO reports it as an xhr poll error.

Wrong URL, path, or port in the test

A hardcoded port that differs from the one the server bound, or a custom path the server does not serve, makes every poll request fail.

How to fix it

Wait for the server to listen before connecting

  1. Bind the server on an ephemeral port and read the actual port back.
  2. Only create the client inside the listen callback (or after await on it).
  3. Point the client at the real bound port.
test.mjs
await new Promise((res) => httpServer.listen(0, res));
const port = httpServer.address().port;
const client = io(`http://localhost:${port}`);

Match the server path and transports

If the server sets a custom path, pass the same path to the client so the poll target exists.

test.mjs
const client = io(url, { path: '/socket', transports: ['websocket', 'polling'] });

How to prevent it

  • Start the server on port 0 and read back the assigned port in tests.
  • Never hardcode a port that a parallel job may also bind.
  • Create the client only after the server is confirmed listening.

Frequently asked questions

What causes ""xhr poll error""?
The client io(url) runs before httpServer.listen(...) has bound the port, so the polling request is refused and Socket.IO reports it as an xhr poll error.
How do I fix "xhr poll error"?
Wait for the server to listen before connecting

Related guides

References

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