Playwright "worker process exited unexpectedly": causes and fixes
By TurnSignal · October 6, 2026 · 5 min read
In short
- Playwright prints
Error: worker process exited unexpectedly (code=…, signal=…)when a worker process died without the runner asking it to stop. - The test that was running fails with that error. Playwright starts a new worker for the remaining tests, and retries the failed one if retries are on.
- Read the code and signal:
signal=SIGKILLusually means the process was killed from outside, most often for running out of memory. A numeric exit code withsignal=nullusually means something calledprocess.exit()or Node crashed. - Fix the cause (memory, workers, a leaking test,
process.exitin test code), and watch for a bigger version of the same problem: a whole CI runner killed, where results disappear instead of failing.
What the error means
Playwright Test runs your tests in worker processes: separate OS processes, each with its own browser, orchestrated by the test runner. When the runner wants a worker to stop, it asks it to. If a worker process ends on its own instead, the runner reports:
Error: worker process exited unexpectedly (code=null, signal=SIGKILL)
In Playwright 1.63 the runner fails the test that was running at that moment with this error and moves the rest of that worker's tests to a new worker. If you have retries set, the failed test is retried like any other failure. If no test was running, for example when the worker died while setting up or tearing down a worker fixture, the error is reported against the next test that worker was going to run.
code and signal values are the first clue.Reading code and signal
Node reports either an exit code or the signal that killed the process, and Playwright prints both:
- `signal=SIGKILL`: the process was killed from outside and could not clean up. On Linux CI machines and in containers the usual sender is the out-of-memory killer. A CI log that shows exit code
137for a step is the same thing seen from the shell: 128 + 9, and 9 is SIGKILL. - `signal=SIGSEGV` or `SIGABRT`: the process crashed. Native modules, a broken Node install or an incompatible binary are typical.
- `signal=SIGTERM` or `SIGINT`: something asked the process to stop, for example a CI job being cancelled or a timeout in the CI system itself.
- `code=1` (or another number) with `signal=null`: the process exited by itself. Look for
process.exit()in test code, helpers or a library, or an uncaught error in code that runs outside a test.
Cause 1: running out of memory
This is the most common cause in CI. Each worker starts its own browser, so memory use grows roughly with the number of workers. A suite that is fine on a laptop with 32 GB can be killed on a 7 GB CI runner, and the worker that happens to cross the line gets the SIGKILL.
Things to try, cheapest first:
- Lower
workersin CI, for exampleworkers: process.env.CI ? 2 : undefined, and see whether the error disappears. If it does, it was memory. - In Docker, run Chromium with
--ipc=host. Playwright's Docker guide says that without it, Chromium can run out of memory and crash. Also use--init, which the same guide recommends to avoid zombie processes. - Look for a test that leaks: pages or contexts opened in a loop and never closed, huge downloads kept in memory, or a test that loads a very heavy page many times. Run the suspect file with
--repeat-eachand watch memory. - Use a bigger runner, or split the suite across more shards so each machine runs fewer tests.
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
workers: process.env.CI ? 2 : undefined,
retries: process.env.CI ? 2 : 0,
});
Cause 2: process.exit() or a crash outside a test
Code that calls process.exit() ends the worker immediately. It can hide in a helper ("exit if the environment variable is missing"), in a global setup imported by a test file, or in a third-party library. Search your test code and helpers for process.exit first. Throw an error instead; Playwright then reports it against the right test and keeps the worker alive.
Cause 3: the CI system stopped the job
When the CI job hits its own time limit or is cancelled, the CI system sends signals to the processes in the job. Workers can report SIGTERM or SIGINT before the main process stops. In this case the fix is in the CI configuration (the job timeout) or in making the suite faster, for example by sharding.
How to find which test was responsible
The test that fails with the error is the one that was running when the worker died, which is not always the one that used the memory. Memory builds up over every test that worker ran. Useful steps:
- Look at which tests ran in the same worker before the crash. Reporters receive the worker index for each attempt, and the
listreporter output shows the order. - Run that file alone with
--workers=1 --repeat-each=10and watch the process memory in another terminal. - Check the CI machine's memory graph or the kernel log (
dmesg) if your CI gives you access; the out-of-memory killer logs the process it killed.
When the whole runner dies
The same problem one level up is worse. If the out-of-memory killer, a spot-instance shutdown or a job timeout kills the whole CI machine, the Playwright runner itself dies with the workers. Then nothing reports the tests that never ran. A sharded run simply shows fewer tests than it should, and the run can even look green. The guide to missing tests after a crashed shard covers how to notice that gap.
TurnSignal is built for this case. The reporter writes results to disk in CI as tests finish, records memory on the machine while the run is going, and compares what reported with the list of tests the run planned. Tests from a runner that stopped responding are listed as Missing with the likely reason, instead of disappearing, and a failure caused by a worker or browser crash is labelled as a crash, with a note when the machine was nearly out of memory. The reporter never changes your exit code. Setup is one line next to your existing reporters; see the docs.
Questions people ask
What does "worker process exited unexpectedly" mean in Playwright?
A worker process (the OS process that runs tests and its browser) ended without the runner asking it to stop. The running test fails with this error and the remaining tests move to a new worker.
What does signal=SIGKILL mean?
The process was killed from outside and could not clean up. In CI and containers this is usually the out-of-memory killer. Lower the number of workers to confirm.
Will retries fix it?
Retries can turn the run green, because the retried test runs in a fresh worker. If the cause is memory, the crash will come back as the suite grows; fix the memory use or the worker count.
Why does the error appear on a test that does nothing heavy?
Memory builds up across every test the worker ran. The test that fails is the one running when the limit was crossed, which may not be the one that used the memory.
Sources
- Playwright docs: Parallelism and worker processes
- Playwright docs: Retries
- Playwright docs: Docker (--ipc=host, --init)
- Node.js docs: child process "exit" event (code and signal)
Playwright details were checked against Playwright 1.63 and its documentation on October 6, 2026.
Try TurnSignal on your next run
Add one reporter line next to your existing reporters. Free to start, no credit card, no repository access.