You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Filing this as a follow-up to #40006 (closed), where a maintainer asked for a
standalone repository with a minimal reproduction:
When you pass FORCE_COLOR=0 or NO_COLOR=1 we just promise you to not send
ansi color into your stdout/stderr, which we hold. The fact that there are
worker processes is Playwright's implementation detail. If you CI is getting
ansi in stdout despite passing FORCE_COLOR=0, please file an issue with a
repro.
git clone https://github.com/veged/playwright-force-color-repro
cd playwright-force-color-repro
npm ci
npx playwright install chromium
npm run repro
The repro script runs:
CI=1 FORCE_COLOR=0 NO_COLOR=1 PLAYWRIGHT_FORCE_TTY=0 \
playwright test tests/repro.spec.js --reporter=dot
The test (tests/repro.spec.js) spawns two node -e ... children from inside
the worker with { env: process.env }:
the first prints the FORCE_COLOR / NO_COLOR values it actually observes
plus a sample string (ANSI only when FORCE_COLOR && FORCE_COLOR !== '0'),
surfaced via console.log as worker-child …;
the second writes raw ANSI bytes directly to stdout
(\u001b[31mRAW_RED\u001b[39m) via process.stdout.write, surfaced as worker-raw ….
With FORCE_COLOR=0 NO_COLOR=1 set in the parent process, the worker should
not override these, and Playwright's host should not let ANSI from a
worker's child reach the final stdout. The two lines should look like:
The worker process tree carries FORCE_COLOR=1, so the first child reports
ANSI-on env, and raw ANSI bytes from the second child reach the final CI
stdout unstripped. Node itself also emits a warning that NO_COLOR is being
ignored because FORCE_COLOR is set:
(node:3010) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.
worker-child {"forceColor":"1","noColor":"1","sample":"\u001b[31mRED\u001b[39m"}
worker-raw ^[[31mRAW_RED^[[39m
i.e. the worker injects FORCE_COLOR=1 into its environment (which is then
inherited by anything the test spawns), and ANSI emitted by a worker-spawned
child is not stripped from the final stdout. NO_COLOR=1 is preserved but FORCE_COLOR=1 wins for libraries that check it first (chalk,
supports-color, etc.) — and Node now states this explicitly via the warning
above.
Suspected source
packages/playwright/src/runner/workerHost.ts (~line 52) sets FORCE_COLOR=1
unconditionally on the worker env regardless of whether the parent process
explicitly disabled colors.
The Node warning The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. is direct evidence from the runtime that the worker's
injected FORCE_COLOR=1 is overriding the caller's NO_COLOR=1.
The behavior breaks pipelines that explicitly disable colors via NO_COLOR / FORCE_COLOR=0 — any tooling spawned from within a test
receives ANSI-on env and emits escape codes into CI logs.
Context
Filing this as a follow-up to #40006 (closed), where a maintainer asked for a
standalone repository with a minimal reproduction:
Repro repository: https://github.com/veged/playwright-force-color-repro
Reproduction
git clone https://github.com/veged/playwright-force-color-repro cd playwright-force-color-repro npm ci npx playwright install chromium npm run reproThe
reproscript runs:The test (
tests/repro.spec.js) spawns twonode -e ...children from insidethe worker with
{ env: process.env }:FORCE_COLOR/NO_COLORvalues it actually observesplus a sample string (ANSI only when
FORCE_COLOR && FORCE_COLOR !== '0'),surfaced via
console.logasworker-child …;(
\u001b[31mRAW_RED\u001b[39m) viaprocess.stdout.write, surfaced asworker-raw ….A push-triggered GitHub Actions workflow (
.github/workflows/repro.yml) runsthe same scenario on
ubuntu-latestwith Node 24, so the failure is visiblein CI logs as well. Latest run on
@playwright/test@1.59.1:https://github.com/veged/playwright-force-color-repro/actions/runs/25467296330
Expected
With
FORCE_COLOR=0 NO_COLOR=1set in the parent process, the worker shouldnot override these, and Playwright's host should not let ANSI from a
worker's child reach the final stdout. The two lines should look like:
Actual
The worker process tree carries
FORCE_COLOR=1, so the first child reportsANSI-on env, and raw ANSI bytes from the second child reach the final CI
stdout unstripped. Node itself also emits a warning that
NO_COLORis beingignored because
FORCE_COLORis set:i.e. the worker injects
FORCE_COLOR=1into its environment (which is theninherited by anything the test spawns), and ANSI emitted by a worker-spawned
child is not stripped from the final stdout.
NO_COLOR=1is preserved butFORCE_COLOR=1wins for libraries that check it first (chalk,supports-color, etc.) — and Node now states this explicitly via the warning
above.
Suspected source
packages/playwright/src/runner/workerHost.ts(~line 52) setsFORCE_COLOR=1unconditionally on the worker env regardless of whether the parent process
explicitly disabled colors.
Environment
@playwright/test1.59.1 (latest stable; also reproduced on 1.58.2, theversion used in [Bug]: Playwright workers force ANSI colors via FORCE_COLOR=1, breaking color-disable behavior in CI/CD #40006)
ubuntu-latestin CI; also reproducible locally on Linux)dotshown above;--reporter=linereproduces the sameworker env)
Notes
PLAYWRIGHT_FORCE_TTY=0is set in the repro to rule out the TTY-detectionpath; the override happens regardless.
worker-rawline specifically addresses the contract articulated in[Bug]: Playwright workers force ANSI colors via FORCE_COLOR=1, breaking color-disable behavior in CI/CD #40006 (
FORCE_COLOR=0/NO_COLOR=1should not result in ANSI in finalstdout/stderr): a child spawned from inside a worker writes raw ANSI bytes
to stdout, and they reach the final GitHub Actions logs unstripped.
The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.is direct evidence from the runtime that the worker'sinjected
FORCE_COLOR=1is overriding the caller'sNO_COLOR=1.NO_COLOR/FORCE_COLOR=0— any tooling spawned from within a testreceives ANSI-on env and emits escape codes into CI logs.