phacility/phabricator · error · PhutilArgumentUsageException

Unable to lock repository "%s": only clustered repositories

Error message

Unable to lock repository "%s": only clustered repositories may be locked.

What it means

Third pre-flight guard in `bin/repository lock`: the repository passes the hosted and VCS-type checks but `getAlmanacServicePHID()` is null, meaning it is not bound to an Almanac "cluster repository" service. Locking exists to fence cluster replicas, so a repository living only on the local disk is rejected. All three checks run before any `PhabricatorGlobalLock` is acquired, so nothing is partially locked.

Source

Thrown at src/applications/repository/management/PhabricatorRepositoryManagementLockWorkflow.php:51

      if (!$repository->isHosted()) {
        throw new PhutilArgumentUsageException(
          pht(
            'Unable to lock repository "%s": only hosted repositories may be '.
            'locked.',
            $display_name));
      }

      if (!$repository->supportsSynchronization()) {
        throw new PhutilArgumentUsageException(
          pht(
            'Unable to lock repository "%s": only repositories that support '.
            'clustering may be locked.',
            $display_name));
      }

      if (!$repository->getAlmanacServicePHID()) {
        throw new PhutilArgumentUsageException(
          pht(
            'Unable to lock repository "%s": only clustered repositories '.
            'may be locked.',
            $display_name));
      }
    }

    $diffusion_phid = id(new PhabricatorDiffusionApplication())
      ->getPHID();

    $locks = array();
    foreach ($repositories as $repository) {
      $engine = id(new DiffusionRepositoryClusterEngine())
        ->setViewer($viewer)
        ->setActingAsPHID($diffusion_phid)
        ->setRepository($repository);

      $event = $engine->newMaintenanceEvent();

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Only run lock against repositories allocated to an Almanac cluster repository service (check Repository → Edit Cluster → service binding).
  2. If clustering is intended, create the Almanac service/bindings and allocate the repository to it, then retry.
  3. On single-server installs, use `bin/repository maintenance` or stop daemons instead of cluster locking.

Example fix

// before
$ ./bin/repository lock R1   # R1 not bound to an Almanac service
[1169] Unable to lock repository "rR1": only clustered repositories may be locked.

// after
$ ./bin/repository maintenance R1 --start "maintenance window"   # non-cluster alternative
Defensive patterns

Strategy: validation

Validate before calling

# Only attempt locking on installs with a cluster repository service;
# verify a repo shows an Almanac service binding (Repository -> Edit Cluster) before locking it.

Type guard

function is_clustered(PhabricatorRepository $repository): bool {
  return $repository->getAlmanacServicePHID() !== null;
}

Prevention

When it happens

Trigger: Running `./bin/repository lock R1` on a single-server install where the repository has no Almanac service binding; a repo allocated to a device instead of a cluster repository service.

Common situations: Operators copy clustering runbook commands onto non-clustered installs; after removing a cluster binding the lock script still targets that repo.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/b9241d2f8327ae2a. Report an issue: GitHub.