{"record":{"id":"c63113056a5a9290","repo":"microsoft/playwright","slug":"err-message-path-lockfilepath","errorCode":null,"errorMessage":"${err.message} Path: ${lockfilePath}","messagePattern":"\\$\\{err\\.message\\} Path: \\$\\{lockfilePath\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/registry/index.ts","lineNumber":951,"sourceCode":"\n  async install(executablesToInstall: Executable[], options?: { force?: boolean, gc?: boolean }) {\n    const executables = this._dedupe(executablesToInstall);\n    await fs.promises.mkdir(registryDirectory, { recursive: true });\n    const lockfilePath = path.join(registryDirectory, '__dirlock');\n    const linksDir = path.join(registryDirectory, '.links');\n\n    let releaseLock;\n    try {\n      releaseLock = await lock(registryDirectory, {\n        retries: {\n          // Retry 20 times during 10 minutes with\n          // exponential back-off.\n          // See documentation at: https://www.npmjs.com/package/retry#retrytimeoutsoptions\n          retries: 20,\n          factor: 1.27579,\n        },\n        onCompromised: (err: Error) => {\n          throw new Error(`${err.message} Path: ${lockfilePath}`);\n        },\n        lockfilePath,\n      });\n      // Create a link first, so that cache validation does not remove our own browsers.\n      await fs.promises.mkdir(linksDir, { recursive: true });\n      await fs.promises.writeFile(path.join(linksDir, calculateSha1(PACKAGE_PATH)), PACKAGE_PATH);\n\n      // Remove stale browsers.\n      if (options?.gc !== false && !getAsBooleanFromENV('PLAYWRIGHT_SKIP_BROWSER_GC'))\n        await this._validateInstallationCache(linksDir);\n\n      // Install browsers for this package.\n      for (const executable of executables) {\n        if (!executable._install)\n          throw new Error(`ERROR: Playwright does not support installing ${executable.name}`);\n\n        if (!getAsBooleanFromENV('CI') && !executable._isHermeticInstallation && !options?.force && executable.executablePath()) {\n          const { embedderName } = getEmbedderName();","sourceCodeStart":933,"sourceCodeEnd":969,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/registry/index.ts#L933-L969","documentation":"Thrown from the onCompromised callback of the proper-lockfile lock() acquired during Registry.install. The underlying lock library reports the lock as 'compromised' — the lockfile/lockdir was removed or overwritten by another process while this install still believed it held the lock. Playwright re-wraps that error and appends the lockfilePath so the offending file is identifiable.","triggerScenarios":"An external process (another Playwright install, a cleanup script, a user) deletes or overwrites the __dirlock file under the registry directory while an install is in progress and still within its retry window; or two concurrent installs race and one invalidates the other's lock.","commonSituations":"Parallel 'npm install' / 'playwright install' invocations in the same CI job sharing one registry directory; a Docker build cache wipe mid-install; antivirus or a tmp-cleanup daemon removing the lock.","solutions":["Re-run the install — the lock is stale and a fresh attempt will usually succeed.","Serialize browser installs so only one Playwright process holds the lock at a time (queue jobs or use a mutex step).","Manually remove the lockfile path shown in the message, then re-run 'npx playwright install'.","Set PLAYWRIGHT_BROWSERS_PATH to isolate installs per job/agent so they no longer contend."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"async function safeInstall(executables, options) {\n  for (let attempt = 0; attempt < 3; attempt++) {\n    try { return await registry.install(executables, options); }\n    catch (e) {\n      if (/Path:/.test(e.message) && attempt < 2) continue;\n      throw e;\n    }\n  }\n}","preventionTips":["Serialize concurrent Playwright installs sharing one registry directory.","Give each CI job its own PLAYWRIGHT_BROWSERS_PATH to avoid lock contention.","Clean up the __dirlock file at the start of a CI step if a prior run may have died."],"tags":["install","lockfile","concurrency","registry"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}