{"record":{"id":"e088912496eda680","repo":"phacility/phabricator","slug":"unable-to-lock-repository-s-only-hosted-reposi","errorCode":null,"errorMessage":"Unable to lock repository \"%s\": only hosted repositories may be locked.","messagePattern":"Unable to lock repository \"(.+?)\": only hosted repositories may be locked\\.","errorType":"exception","errorClass":"PhutilArgumentUsageException","httpStatus":null,"severity":"error","filePath":"src/applications/repository/management/PhabricatorRepositoryManagementLockWorkflow.php","lineNumber":35,"sourceCode":"            'wildcard' => true,\n          ),\n        ));\n  }\n\n  public function execute(PhutilArgumentParser $args) {\n    $viewer = $this->getViewer();\n\n    $repositories = $this->loadRepositories($args, 'repositories');\n    if (!$repositories) {\n      throw new PhutilArgumentUsageException(\n        pht('Specify one or more repositories to lock.'));\n    }\n\n    foreach ($repositories as $repository) {\n      $display_name = $repository->getDisplayName();\n\n      if (!$repository->isHosted()) {\n        throw new PhutilArgumentUsageException(\n          pht(\n            'Unable to lock repository \"%s\": only hosted repositories may be '.\n            'locked.',\n            $display_name));\n      }\n\n      if (!$repository->supportsSynchronization()) {\n        throw new PhutilArgumentUsageException(\n          pht(\n            'Unable to lock repository \"%s\": only repositories that support '.\n            'clustering may be locked.',\n            $display_name));\n      }\n\n      if (!$repository->getAlmanacServicePHID()) {\n        throw new PhutilArgumentUsageException(\n          pht(\n            'Unable to lock repository \"%s\": only clustered repositories '.","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/repository/management/PhabricatorRepositoryManagementLockWorkflow.php#L17-L53","documentation":"Thrown by `bin/repository lock` during its pre-flight loop when a target repository has `isHosted()` false — i.e. it is an observed/remote repository that Phabricator mirrors in read-only fashion rather than hosting itself. Locking exists to block cluster writes, so it is only meaningful for hosted repositories; the workflow aborts before acquiring any locks.","triggerScenarios":"Running `./bin/repository lock R2` where R2 is configured as \"Observe a remote repository\" or \"Import an existing repository\" (not hosted); locking a list that mixes hosted and observed repos — the first observed one aborts the whole run.","commonSituations":"Installations that primarily mirror upstream repos point the lock command at a mirror; after flipping a repo from hosted to observed, old lock scripts keep targeting it.","solutions":["Target only hosted repositories: check Repositories → Edit Hosting and pick ones where Phabricator hosts the working copy.","Convert the repository to hosted (Repository → Edit → Hosting → Host, configure serving) if it should be lockable.","If you meant a read-only mirror, skip locking — there are no cluster writes to block.","Filter your target list in advance: host a script that checks `isHosted()` (or the hosting setting in the UI) before invoking lock."],"exampleFix":"// before\n$ ./bin/repository lock R2   # R2 is an observed mirror\n[1167] Unable to lock repository \"rR2\": only hosted repositories may be locked.\n\n// after\n$ ./bin/repository lock R1   # R1 is hosted\n// or: Repository R2 -> Edit Hosting -> \"Host a repository\" first","handlingStrategy":"validation","validationCode":"# Only lock repos that Phabricator hosts (checked via Conduit or the UI);\n# shell-level: maintain an explicit allowlist of hosted callsigns.\nfor r in R1 R2; do grep -qx \"$r\" hosted-repos.txt || { echo \"skip $r (not hosted)\"; continue; }; ./bin/repository lock \"$r\"; done","typeGuard":"function is_lockable(PhabricatorRepository $repository): bool {\n  return $repository->isHosted()\n    && $repository->supportsSynchronization()\n    && (bool)$repository->getAlmanacServicePHID(); // covers [1167]-[1169] in one check\n}","tryCatchPattern":null,"preventionTips":["Keep a curated list of hosted, clustered repositories for maintenance scripts instead of passing wildcards.","Check the Hosting setting in the repository UI before adding a repo to lock procedures."],"tags":["phabricator","phorge","cli","locking","hosted-repository","precondition"],"backgroundTag":"repository-not-hosted","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}