skip to content

In Playwright, what does the --max-failures flag do, and what is -x short for?

level: juniorimportance: should knowfreq 55%

answer

  1. A budget for the run, not a test
  2. Counts failed tests across all workers
  3. One-letter shorthand for stop-on-first
  4. Same knob exists in the config file
  5. Untouched tests are not passes

basics

~10 s

In Playwright, --max-failures=N stops the whole run once N tests have failed; the remaining tests never start. The shorthand -x means --max-failures=1, so the run aborts on the first failed test.

solid answer

~40 s

`--max-failures=N` is a budget for the **entire run**, not for one test. Playwright counts failed tests across all workers and projects, and as soon as the count reaches `N` it stops scheduling new tests, interrupts the ones still in flight, and shuts the workers down. `-x` is simply the shorthand for `--max-failures=1`. The same setting exists in the config file as `maxFailures`, where `0` (the default) means no limit, and the CLI flag overrides the config value. What it counts is *tests*, not assertions and not retry attempts: a test that fails and then passes on a retry does not consume the budget. The run still exits non-zero, and the tests that were never reached are reported as not run rather than as passing.

code

bash · 9 lines
bash
# Abort the payroll suite on the first failed test
npx playwright test -x

# Or allow a handful of failures before giving up
npx playwright test --max-failures=5

# The same ceiling, baked into playwright.config.ts:
#   export default defineConfig({ maxFailures: 5 })
# A CLI value overrides the config value for that run.

go deeper

for a junior

Remember the two forms: --max-failures=N stops the run after N failed tests, and -x is the same thing with N of one. Reach for -x when you are debugging locally and want the first red test immediately.

for a middle

Explain that the ceiling is counted across workers and projects, that it counts tests rather than assertions or attempts, and that the config file spells it maxFailures with zero meaning no limit.

for a senior

Show judgment about which jobs deserve it: a fast pre-merge run yes, a nightly job that must produce complete evidence no. Mention that unreached tests report as not run and that a sharded run applies the ceiling per shard.

for a principal

Own the trade explicitly: fail-fast buys runner time by giving up information about the rest of the suite. Decide where that trade is acceptable across the estate rather than letting each job invent its own ceiling.

`--max-failures` is Playwright's fail-fast switch: it puts a ceiling on how many failed tests a single run is willing to collect before it gives up. On a large regression suite for a payroll product in CI, this is the difference between learning in ninety seconds that the login fixture is broken and paying forty minutes to watch every payslip test fail the same way. ## What the flag does `--max-failures=N` is a **whole-run** budget. Playwright keeps a running count of failed tests across every worker process and every project in the run. The moment that count reaches `N`: - it stops handing out new tests to workers; - it interrupts the tests that are still executing; - it shuts the workers down and finalises the reporters; - it exits with a non-zero status, exactly as an ordinary failing run does. `-x` is not a separate feature — it is the documented shorthand for `--max-failures=1`, the "stop on the first failure" mode you reach for when debugging locally. ## What it counts, and what it does not The budget counts **tests**, not assertions and not attempts. Two details follow from that: 1. A test that fails and then passes on a retry is *flaky*, not failed, and does not consume the budget. 2. A test that exhausts its retries and stays red consumes exactly one unit, no matter how many attempts it took. It also does not touch what happens *inside* a test: a per-test timeout or a failed assertion still ends only that test. `--max-failures` acts one level up, on the scheduler. ## The config twin The same control exists in `playwright.config.ts` as `maxFailures`, so a team can bake it in rather than remembering a flag. | Form | Where it lives | Typical use | |---|---|---| | `-x` | CLI | Local debugging: abort on the first red test | | `--max-failures=N` | CLI | A one-off capped run, or a CI job that passes the value in | | `maxFailures: N` | `playwright.config.ts` | The team-wide default for every invocation | The default is `0`, which means **no limit** — the run always goes to the end. A command-line value overrides the config value for that invocation. ## What happens to the tests that never ran This is the part candidates get wrong. Aborting early does not mean the rest passed: - Unreached tests appear in the report as **not run**, not as passing, so a truncated run is visibly incomplete. - The exit code is still non-zero, so a pipeline stage keyed on it fails as it should. - Because the suite is truncated, the run tells you *that* something is broken, not *how much* is broken — you have traded coverage of this run for speed. That trade is why fail-fast is a poor fit for a nightly full-regression job, where the whole point is a complete picture, and a good fit for a fast pre-merge job whose only question is "is this branch worth running further?". ## Interactions worth knowing - Each shard is its own process with its own count, so a value set on a sharded run is applied **per shard**, not across the whole matrix. - With several workers in flight, the run can finish with slightly *more* than `N` failures: tests already executing when the ceiling is hit may fail before they are interrupted. Treat `N` as a threshold, not an exact quota. - On a suite that hangs rather than fails, `--max-failures` never triggers at all — there are no failures to count. A wall-clock cap such as `globalTimeout` is the control for that case. ## Common mistakes - Reading `-x` as "exit quietly" or as a headless switch; it is purely `--max-failures=1`. - Expecting the report to show the untouched tests as green. - Setting `maxFailures: 1` on the suite that produces the release evidence, then wondering why the report only ever contains one failure.

  • Does a test that fails once and passes on a retry count against --max-failures?
    No. Playwright counts tests whose final outcome is failed. A test that fails and then passes on a retry is reported as flaky and leaves the budget untouched. Only a test that stays red after its last attempt consumes one unit of the ceiling.
  • Why can a run with --max-failures=3 finish with four failures?
    Workers run in parallel. When the third failure pushes the count to the ceiling, other workers may already be mid-test; those tests can fail before the interrupt reaches them. The value is a threshold that stops further scheduling, not an exact quota of failures.

saying these in an interview costs you the question

  • Thinks -x means headless or quiet output
  • Believes it limits retry attempts of a single test
  • Says the tests that never ran are reported as passed
  • Assumes an aborted run exits with status zero
  • Thinks it counts failed assertions rather than failed tests
  • Expects it to rescue a suite that hangs without failing