Skip to content
Latchkey

Puppeteer "Navigation timeout of 30000 ms exceeded" in CI

page.goto and waitForNavigation default to a 30 second budget and a load condition such as networkidle. If the app is slow in CI, or the wait condition (like networkidle0) never settles, Puppeteer throws "Navigation timeout of 30000 ms exceeded".

What this error means

A test fails with "TimeoutError: Navigation timeout of 30000 ms exceeded" at a page.goto or page.waitForNavigation call, often on a runner slower than the developer machine.

puppeteer
TimeoutError: Navigation timeout of 30000 ms exceeded
    at new Waiter (.../puppeteer/lib/cjs/puppeteer/common/LifecycleWatcher.js)
    at Page.goto (.../puppeteer/lib/cjs/puppeteer/common/Page.js)

Common causes

The app responded slower than 30 seconds

A cold or contended backend in CI made the page load exceed the default navigation timeout.

The waitUntil condition never settled

networkidle0 waits for zero in-flight requests; a page with long-polling or analytics beacons never reaches that state.

How to fix it

Raise the timeout and use a reachable waitUntil

  1. Increase the navigation timeout for CI.
  2. Use domcontentloaded or load instead of networkidle0 when background requests never stop.
  3. Re-run so navigation resolves within budget.
JavaScript
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });

Wait for the app to be ready first

Health-check the server before navigating so the first load is not racing a cold start.

.github/workflows/ci.yml
- run: curl --retry 10 --retry-connrefused http://localhost:3000/healthz

How to prevent it

  • Set CI navigation timeouts above the local default.
  • Avoid networkidle0 on pages with continuous background traffic.
  • Health-check the app before the first navigation.

Related guides

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