{"record":{"id":"f4d56cf0f001bbe2","repo":"phacility/phabricator","slug":"failed-to-acquire-write-lock-after-waiting-s-seco","errorCode":null,"errorMessage":"Failed to acquire write lock after waiting %s second(s). You may be able to retry later. (%s)","messagePattern":"Failed to acquire write lock after waiting (.+?) second\\(s\\)\\. You may be able to retry later\\. \\((.+?)\\)","errorType":"exception","errorClass":"PhutilProxyException","httpStatus":null,"severity":"error","filePath":"src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php","lineNumber":382,"sourceCode":"\n        // Wait a little longer before the next message we print.\n        $step_wait = $step_wait + 0.5;\n        $step_wait = min($step_wait, 3);\n      }\n\n      $waited = (PhabricatorTime::getNow() - $start);\n      if ($waited) {\n        $this->logLine(\n          pht(\n            'Acquired write lock after %s second(s).',\n            new PhutilNumber($waited)));\n      } else {\n        $this->logLine(\n          pht(\n            'Acquired write lock immediately.'));\n      }\n    } catch (PhutilLockException $ex) {\n      throw new PhutilProxyException(\n        pht(\n          'Failed to acquire write lock after waiting %s second(s). You '.\n          'may be able to retry later. (%s)',\n          new PhutilNumber($lock_wait),\n          $ex->getHint()),\n        $ex);\n    }\n\n    $versions = PhabricatorRepositoryWorkingCopyVersion::loadVersions(\n      $repository_phid);\n    foreach ($versions as $version) {\n      if (!$version->getIsWriting()) {\n        continue;\n      }\n\n      throw new Exception(\n        pht(\n          'An previous write to this repository was interrupted; refusing '.","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php#L364-L400","documentation":"Before a push (write) can proceed, the engine acquires the repository's global write lock with a bounded wait; a PhutilLockException timeout is wrapped in a PhutilProxyException that preserves the wait budget and the lock hint. Another device or daemon held the write lock longer than the wait budget, so the write was aborted before any mutation began.","triggerScenarios":"A push arrives while another device's push, or a long-running sync/pull, holds the repository write lock; the losing writer times out. Frequently seen with CI systems pushing to clustered repositories.","commonSituations":"Frequent pushes from multiple cluster nodes; large pushes competing with heavy pulls; stale write locks after a daemon crash; manual bin/repository commands overlapping with push traffic.","solutions":["Retry the push: the abort happened before any data changed, and lock contention under concurrent writes is expected","Stagger scheduled pushes and discovery so write work and heavy read work do not overlap on the same repository","If pushes consistently fail, locate the stuck lock holder via daemon logs and bin/phd status, and restart that daemon to clear a leaked lock"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"$attempts = 3;\nfor ($i = 0; $i < $attempts; $i++) {\n  try {\n    return $engine->synchronizeWorkingCopyBeforeWrite();\n  } catch (PhutilProxyException $ex) {\n    if (!($ex->getPrevious() instanceof PhutilLockException)) {\n      throw $ex;\n    }\n    sleep(5 * (2 ** $i));\n  }\n}\n// surface a 'repository busy, push aborted before any changes' error to the pusher\nthrow $ex;","preventionTips":["Stagger CI pushes so concurrent writers do not fight for the write lock","Keep heavy pulls/discovery off push windows for large repositories","Restart daemons that leak write locks rather than letting pushes fail forever"],"tags":["locking","concurrency","cluster","push","timeout"],"backgroundTag":"lock-acquisition-timeout","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}