phacility/phabricator · error · PhutilAggregateException

Exceptions occurred while mirroring the "%s" repository.

Error message

Exceptions occurred while mirroring the "%s" repository.

What it means

Thrown by PhabricatorRepositoryMirrorEngine after attempting to push a repository to every configured mirror when one or more pushes threw. The individual exceptions are collected and re-raised wrapped in a PhutilAggregateException naming the repository; inspect the aggregated exceptions to see each mirror's real failure such as auth, DNS, or non-fast-forward. Mirroring is best-effort per mirror, but any failure surfaces as this aggregate error in the task or daemon log.

Source

Thrown at src/applications/repository/engine/PhabricatorRepositoryMirrorEngine.php:49

    foreach ($uris as $mirror) {
      if ($mirror->getIsDisabled()) {
        continue;
      }

      $io_type = $mirror->getEffectiveIOType();
      if ($io_type != $io_mirror) {
        continue;
      }

      try {
        $this->pushRepositoryToMirror($repository, $mirror);
      } catch (Exception $ex) {
        $exceptions[] = $ex;
      }
    }

    if ($exceptions) {
      throw new PhutilAggregateException(
        pht(
          'Exceptions occurred while mirroring the "%s" repository.',
          $repository->getDisplayName()),
        $exceptions);
    }
  }

  private function pushRepositoryToMirror(
    PhabricatorRepository $repository,
    PhabricatorRepositoryURI $mirror_uri) {

    $this->log(
      pht(
        'Pushing to remote "%s"...',
        $mirror_uri->getEffectiveURI()));

    if ($repository->isGit()) {
      $this->pushToGitRepository($repository, $mirror_uri);

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Read the wrapped exceptions inside the aggregate (daemon log or task detail); the actual fix is always in the per-mirror error
  2. Test each mirror URI by hand as the daemon user with the exact git or ssh URL to reproduce the real failure
  3. If SSH host key is the issue, connect once manually to accept it or add it to the daemon known_hosts
  4. If a mirror diverged (non-fast-forward), align it by re-cloning from Phabricator or force-updating the mirror, then let the next mirror cycle run
  5. Confirm each mirror URI has the correct mirror I/O type on the repository URIs screen
Defensive patterns

Strategy: try-catch

Validate before calling

// Before the mirror cycle, smoke-test each mirror URI from the daemon host:
//   git ls-remote <mirror_uri>   (expect exit code 0)
// A failure here predicts the aggregate exception later.

Try / catch

try {
  id(new PhabricatorRepositoryMirrorEngine())
    ->setRepository($repository)
    ->pushToMirrors();
} catch (PhutilAggregateException $ex) {
  foreach ($ex->getAggregateExceptions() as $mirror_ex) {
    phlog('Mirror failure: '.$mirror_ex->getMessage()); // fix these individually
  }
}

Prevention

When it happens

Trigger: A mirror URI with wrong or expired credentials; mirror host unreachable due to firewall or DNS; SSH host key not yet trusted; git push rejected as non-fast-forward after the mirror diverged; mirror URI misconfigured as a normal read/write remote instead of a mirror.

Common situations: Credentials rotated on the mirror server but not updated in the repository URI config; mirror VM down for maintenance while the mirror daemon runs; first push to a new mirror before its host key was accepted; mirrors that received manual pushes and diverged.

Related errors


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