playwright ECONNREFUSED on YOUR_HOST in CI
Fixes Playwright connection-refused errors when the app server is not reachable in CI. Use when tests fail connecting to YOUR_HOST in CI but work locally. Not for DNS failures.
TL;DR
The test tried to reach the app server and nothing was listening. Start the server before the tests in CI (webServer config or start-server-and-test), bind it to all interfaces if the browser runs in a separate container, and verify with curl before the test step.
Error
Error: page.goto: net::ERR_CONNECTION_REFUSED at YOUR_HOST/Steps
- Add a
webServerblock toplaywright.config.tswith the dev command, URL, andreuseExistingServer: !process.env.CI. Expected: Playwright starts the server and waits for the URL. - If the browser runs in a separate container, bind the server to
the all-interfaces addressand point tests at the service name, not YOUR_HOST. Expected: cross-container networking works. - Add a pre-test curl check in CI:
curl --retry 10 --retry-delay 2 YOUR_HOST/health. Expected: the pipeline fails fast with a clear message instead of 50 test timeouts. - Check the port: CI services sometimes claim different ports than local. Print the actual listening port in the server logs. Expected: config port matches reality.
- Re-run the CI job. Expected: goto succeeds because the server is provably up.
When to use
ERR_CONNECTION_REFUSEDin CI, green locally.- The app server is started by the pipeline, not already running.
When not to use
- DNS failures (
ERR_NAME_NOT_RESOLVED). - The server is up but returns 500s (app bug).
Tool compatibility
- Playwright 1.30 through latest;
webServerconfig; any CI provider.
Variant phrasings
Playwright could not connect to YOUR_HOST:3000 in CI
Same root cause; the server lifecycle is the fix.
webServer timeout waiting for URL
The server took too long to boot; raise the webServer timeout, not the test timeout.
Why it happens
Locally the dev server is already running from your terminal. In CI nothing is running unless the pipeline starts it, and tests race the boot.
Edge cases
reuseExistingServer: truein CI hides the problem locally but breaks CI; gate it on!process.env.CI.- Databases also need to be up; a refusing DB looks like an app failure one layer down.
- IPv6 YOUR_HOST (
the loopback address) vs IPv4 (the loopback address) mismatches cause refuses that curl with the other family would catch.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst5yQTGW-kae-ZRamllnhcQ
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.