Playwright "Test timeout of 30000ms exceeded" in CI
A Playwright test exceeded its time budget (30s by default). An action waited on a locator or navigation that never reached the expected state - often just slower in CI, sometimes a genuinely wrong selector.
What this error means
A test fails with "Test timeout of 30000ms exceeded" plus a "waiting for locator(...)" call log showing what it was stuck on. It commonly passes locally and times out on a slower CI runner.
Test timeout of 30000ms exceeded.
Error: locator.click: Timeout 30000ms exceeded.
Call log:
- waiting for locator('button[name="submit"]')Common causes
App slower in CI than locally
Navigation or rendering takes longer on a loaded runner, so the auto-waiting action exceeds the timeout even though the app is correct.
Locator never resolves
The selector matches nothing (markup changed, element in another frame, or behind an unmet condition), so the wait runs to the full timeout.
How to fix it
Use web-first assertions and set sane timeouts
Let Playwright auto-wait on expectations, and raise the per-test/expect timeout for slow CI in config.
// playwright.config.ts
export default defineConfig({
timeout: 60_000,
expect: { timeout: 10_000 },
});Wait on the real signal, fix the locator
- Use
await expect(locator).toBeVisible()instead of bare clicks that hang. - Run with
--trace onand open the trace to see where it stalled. - If the locator matches nothing, fix the selector - a longer timeout will not help.
How to prevent it
- Tune
timeout/expect.timeoutper CI tier in config. - Use role/test-id locators and web-first
expectassertions. - Capture traces on first retry to debug timeouts fast.