[Bug]: UI mode fails with spawn EBADF on macOS when the test directory contains more than ~10k files

Cerrado
#43,653 2 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@guishiw ya está trabajando en esto.

Desde el 28/10/2026.

  • #43712 de @guishiw — abierto
  • #43716 de @dgozman — abierto

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
55/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
macos, node.js, typescript
Área
devtools, testing

Línea de trabajo

Start with WorkerHost.startRunner in node_modules/playwright/lib/runner/index.js and trace how UI mode's FSWatcher and chokidar handle the test directory before worker processes are spawned. Reproduce on macOS using the supplied config, one test, and roughly 11,000 files; compare with a non-UI run. Done means UI mode runs and passes the test without spawn EBADF at that scale.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

needs-triage-mac
Version

1.64.1 (also reproduced on 1.63.0)

Steps to reproduce
  1. Create a project with this playwright.config.ts:

    import { defineConfig } from '@playwright/test';
    
    export default defineConfig({
      testDir: './',
      testMatch: '**/*.spec.ts',
    });
    
  2. Add one trivial test, example.spec.ts:

    import { expect, test } from '@playwright/test';
    
    test('passes', () => {
      expect(1 + 1).toBe(2);
    });
    
  3. Put 11,000 plain files under testDir:

    mkdir src && for i in $(seq 0 10999); do echo "export const v$i = $i;" > src/file-$i.ts; done
    
  4. Run npx playwright test --ui and click Run all.

Expected behavior

The test runs and passes, as it does with npx playwright test without --ui.

Actual behavior

No test runs (0/0). The output pane shows:

Error: spawn EBADF
Error: spawn EBADF

The full stack, from a real project on 1.63.0:

Error: spawn EBADF
    at ChildProcess.spawn (node:internal/child_process:486:11)
    at spawn (node:child_process:860:9)
    at Object.fork (node:child_process:177:10)
    at WorkerHost.startRunner (node_modules/playwright/lib/runner/index.js:1915:49)
    at WorkerHost.start (node_modules/playwright/lib/runner/index.js:5473:23)
    at Dispatcher._runJobInWorker (node_modules/playwright/lib/runner/index.js:5600:20) {
  errno: -9,
  code: 'EBADF',
  syscall: 'spawn'
}

With 9,000 files instead of 11,000, the same project passes in UI mode.

Additional context

Cause. In UI mode, FSWatcher watches the project testDir (plus test dependencies) with the bundled chokidar. On macOS this keeps one open file descriptor per watched file. In our real project the UI-mode process held 10,658 open descriptors, about 10,600 of them regular files under testDir.

When a process holds more than macOS OPEN_MAX (10240) descriptors, the new stdio pipes for the worker get fd numbers above that limit. fork() with piped stdio then fails with EBADF. Raising ulimit -n doesn't help; ours is 1048576.

The same failure without Playwright:

// ebadf.cjs — node ebadf.cjs x 10200 → "ok"; node ebadf.cjs x 10300 → "EBADF"
const fs = require('fs');
const { fork } = require('child_process');

if (process.argv[2] === 'child') process.exit(0);

const n = Number(process.argv[3]);
for (let i = 0; i < n; i++) fs.openSync(__filename, 'r');
try {
  const child = fork(__filename, ['child'], { stdio: ['ignore', 'pipe', 'pipe', 'ipc'] });
  child.on('exit', () => console.log(n, 'ok'));
} catch (e) {
  console.log(n, e.code);
}

So any project with more than ~10k files under testDir cannot run tests in UI mode on macOS. Non-UI runs are not affected because they don't start the watcher.

Possible fixes.

  • Use a watcher that does not hold one descriptor per file on macOS, such as FSEvents or recursive fs.watch.
  • Watch only the test files and their dependencies, not every file under testDir.
  • Let users exclude paths from the UI-mode watcher.

Workaround. Narrow testDir so it contains fewer than ~10k files.

Environment
System:
  OS: macOS 27.0.1 (26A434), arm64
Binaries:
  Node: 26.12.1
npmPackages:
  @playwright/test: 1.64.1 (also 1.63.0)
Lenguaje dominante
TypeScript
Estrellas
98.5k
Forks
6.7k
Merge medio
17 h 15 min
PR fusionados (30 d)
311

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de microsoft/playwright

Todos los issues de microsoft/playwright

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.