Skip to content

[Bug]: Windows console window pops up when launching chrome-headless-shell (processLauncher missing windowsHide) #41630

Closed as not planned

Description

@tomfluff

System info

  • Playwright: 1.58.2 (playwright-core)
  • OS: Windows 11 (10.0.26200)
  • Node: v22.23.1
  • Browser: Chromium (chrome-headless-shell, headless)

Summary

On Windows, launching Chromium opens a console window (a Windows Terminal window on Win11) for chrome-headless-shell.exe. The browser process is spawned without windowsHide, so chrome-headless-shell (a console-subsystem binary) gets a console window.

Root cause

src/server/utils/processLauncher.js builds spawnOptions with detached but never windowsHide:

const spawnOptions = {
  detached: process.platform !== "win32",
  env: options.env,
  cwd: options.cwd,
  shell: options.shell,
  stdio
};
const spawnedProcess = childProcess.spawn(options.command, options.args || [], spawnOptions);

On Windows, childProcess.spawn without windowsHide: true allocates a console window (windowsHide → CREATE_NO_WINDOW).

Fix

   const spawnOptions = {
     detached: process.platform !== "win32",
+    windowsHide: true,
     env: options.env,
     cwd: options.cwd,
     shell: options.shell,
     stdio
   };

Verification

Patched processLauncher.js in node_modules locally, restarted — the chrome-headless-shell console window no longer appears (confirmed via EnumWindows). Windows-only; no-op elsewhere.

Activity

  1. triemerge commented on Jul 6, 2026

    @triemerge
    Contributor

    This was actually fixed in #38776 but had to be reverted (#39994) because windowsHide: true was added unconditionally to launchProcess(), and that ended up hiding Inspector and codegen windows too since they go through the same path.

    I think the fix here is to make it opt-in so only headless launches get it. Will put up a PR.

  2. pavelfeldman commented on Jul 6, 2026

    @pavelfeldman
    Member

    On Windows, launching Chromium opens a console window (a Windows Terminal window on Win11) for chrome-headless-shell.exe. The browser process is spawned without windowsHide, so chrome-headless-shell (a console-subsystem binary) gets a console window.

    Can't reproduce this. Please share exact steps.

  3. triemerge commented on Jul 6, 2026

    @triemerge
    Contributor

    On Windows, launching Chromium opens a console window (a Windows Terminal window on Win11) for chrome-headless-shell.exe. The browser process is spawned without windowsHide, so chrome-headless-shell (a console-subsystem binary) gets a console window.

    Can't reproduce this. Please share exact steps.

    #40741 might be worth a look since it covers the same underlying thing.

  4. dgozman commented on Jul 14, 2026

    @dgozman
    Collaborator

    We tried hard reproducing this issue, but were not able to. This seems very specific to your setup. Without a repro, we are not going to risk breaking users, sorry.

  5. mxschmitt commented on Jul 14, 2026

    @mxschmitt
    Contributor

    Dmitry Gozman (@dgozman) did you try reproducing with #40741 (comment)? This is similar to when other tools wrap Playwright e.g. coding agents and then it ends up in a similar issue.

  6. Vistritium commented on Jul 14, 2026

    @Vistritium

    I don't have complicated setup, I use playwright-cli with codex and it happens all the time when codex is using playwright-cli.

  7. tomfluff commented on Jul 17, 2026

    @tomfluff
    Author

    Thank you all for the comments and attempts to reproduce! For context, I use playwright-cli through gstack and it happened a lot. I also had to make some changes there which I opened a PR for (garrytan/gstack#2182 (comment)). I tried only the changes there without the playwright-cli changes and it seems to still happen so the change here might be important for it all to work.

  8. vinhch commented on Aug 7, 2026

    @vinhch

    Possibly relevant, though I'm not sure it's the same thing this issue describes.

    #42152 reported a console window from a different spawn site (the CLI session daemon) and was fixed in #42155, which also happened to touch the taskkill spawn inside launchProcess:

    -const taskkillProcess = childProcess.spawnSync(`taskkill /pid ${pid} /T /F`, { shell: true });
    +const taskkillProcess = childProcess.spawnSync(`taskkill /pid ${pid} /T /F`, { shell: true, windowsHide: true });

    That taskkill one is what I ran into on Windows 11 with @playwright/cli 0.1.18. The visible window belongs to cmd.exe /d /s /c "taskkill /pid <browser> /T /F", spawned by the detached cliDaemon.js. Adding windowsHide to that single line makes it go away and reverting it brings it back. One thing that tripped me up while checking: counting processes doesn't show any difference, since CREATE_NO_WINDOW still allocates a conhost, just an invisible one. I had to poll EnumWindows + IsWindowVisible before the change was visible at all.

    Whether that shares a root cause with the chrome-headless-shell window reported here, I genuinely can't say — my setup launches chrome.exe, so I never touch the browser spawn path. The only thing that looks common across the reports is a parent process with no console to inherit. #40741 described that setup, but it was closed before the recipe got tried here. If that really is the precondition, it might be why it doesn't show up when running from a normal terminal.

    Not asking for the decision to be revisited, just leaving the cross-link — #42155 isn't mentioned anywhere on this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions