microsoft/playwright · error · Error
An active lockfile is found at: ${lockfilePath} Either:
Error message
An active lockfile is found at:
${lockfilePath}
Either:
- wait a few minutes if other Playwright is installing browsers in parallel
- remove lock manually with:
${rmCommand} ${lockfilePath}
<3 Playwright Team What it means
Thrown from the catch block of Registry.install when the lock acquisition fails with error code ELOCKED — the proper-lockfile library exhausted all 20 retries over ~10 minutes without obtaining the lock. The boxed message tells the user another Playwright process holds the lock and gives the manual removal command for the platform.
Source
Thrown at packages/playwright-core/src/server/registry/index.ts:994
`requires *removal* of a current installation first.`,
``,
`To *uninstall* current version and re-install latest "${executable.name}":`,
``,
`- Close all running instances of "${executable.name}", if any`,
`- Use "--force" to install browser:`,
``,
` ${command}`,
``,
`<3 Playwright Team`,
].join('\n'), 1) + '\n\n');
return;
}
await executable._install(!!options?.force);
}
} catch (e) {
if (e.code === 'ELOCKED') {
const rmCommand = process.platform === 'win32' ? 'rm -R' : 'rm -rf';
throw new Error('\n' + wrapInASCIIBox([
`An active lockfile is found at:`,
``,
` ${lockfilePath}`,
``,
`Either:`,
`- wait a few minutes if other Playwright is installing browsers in parallel`,
`- remove lock manually with:`,
``,
` ${rmCommand} ${lockfilePath}`,
``,
`<3 Playwright Team`,
].join('\n'), 1));
} else {
throw e;
}
} finally {
if (releaseLock)
await releaseLock();View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Run the rm command printed in the message ('rm -rf <path>' on macOS/Linux, 'rm -R <path>' on Windows) then re-run the install.
- Wait and retry if another install is legitimately running.
- Isolate installs with a unique PLAYWRIGHT_BROWSERS_PATH per concurrent job.
- Add a lock-cleanup step at the start of CI: remove the __dirlock file before installing.
Defensive patterns
Strategy: retry
Validate before calling
import { existsSync, rmSync } from 'fs';
import { join } from 'path';
// Remove a stale lock before installing
const lock = join(process.env.PLAYWRIGHT_BROWSERS_PATH || '', 'ms-playwright', '__dirlock');
if (existsSync(lock)) rmSync(lock, { recursive: true, force: true }); Try / catch
try {
await registry.install(executables);
} catch (e) {
if (e.code === 'ELOCKED' || /active lockfile is found/.test(e.message)) {
// wait briefly, remove stale lock, retry once
rmSync(lockfilePath, { recursive: true, force: true });
await registry.install(executables);
} else throw e;
} Prevention
- Remove the __dirlock at the start of CI steps where a prior install may have been killed.
- Use a unique PLAYWRIGHT_BROWSERS_PATH per concurrent job to avoid contention.
- Do not run two 'playwright install' commands against the same registry directory in parallel.
When it happens
Trigger: A prior 'playwright install' crashed without releasing the __dirlock, or a long-running concurrent install still holds it; subsequent installs retry for 10 minutes then surface this error.
Common situations: CI job that was killed mid-install leaving a stale lock; multiple pipeline stages installing browsers into the same PLAYWRIGHT_BROWSERS_PATH simultaneously; local dev interrupted an install with Ctrl-C.
Related errors
- ${err.message} Path: ${lockfilePath}
- Executable doesn't exist at ${e} ${wrapInASCIIBox(prettyMess
- WebKit via WSL is only supported on Windows
- Failed to install WebKit via WSL
- ERROR: Playwright does not support installing ${executable.n
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/d56bb1b124128eed.
Report an issue: GitHub.