phacility/phabricator · error · Exception

Unable to load diff "%s".

Error message

Unable to load diff "%s".

What it means

Before landing, the operation loads the exact Differential diff recorded on the operation (property `differential.diffPHID`) to find the staging ref to merge. If the property is empty or the diff query (run with the operation viewer's permissions) cannot load it, land aborts with this Exception. The diff is normally attached when the land request is created, so a failure means the property was never set, the diff was deleted, or the viewer cannot see it.

Source

Thrown at src/applications/drydock/operation/DrydockLandRepositoryOperation.php:205

    return array(
      'name' => $committer_name,
      'email' => 'autocommitter@example.com',
    );
  }

  private function loadDiff(DrydockRepositoryOperation $operation) {
    $viewer = $this->getViewer();
    $revision = $operation->getObject();

    $diff_phid = $operation->getProperty('differential.diffPHID');

    $diff = id(new DifferentialDiffQuery())
      ->setViewer($viewer)
      ->withPHIDs(array($diff_phid))
      ->executeOne();
    if (!$diff) {
      throw new Exception(
        pht(
          'Unable to load diff "%s".',
          $diff_phid));
    }

    $diff_revid = $diff->getRevisionID();
    $revision_id = $revision->getID();
    if ($diff_revid != $revision_id) {
      throw new Exception(
        pht(
          'Diff ("%s") has wrong revision ID ("%s", expected "%s").',
          $diff_phid,
          $diff_revid,
          $revision_id));
    }

    return $diff;
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Inspect the operation's `differential.diffPHID` property — if empty, the operation was created incorrectly; re-request the land from the revision UI so the current diff is attached
  2. If set, verify that PHID exists via `differential.diff.search` and is visible to the operation's author
  3. If the diff was deleted, abandon the operation and land the current diff afresh
  4. In custom creation code, always copy `$revision->getActiveDiff()->getPHID()` onto the operation properties

Example fix

// before
$operation->setPropertyValue('differential.diffPHID', null); // or omitted
// later: Exception: Unable to load diff "".

// after
$diff_phid = $revision->getActiveDiff()->getPHID();
$operation->setPropertyValue('differential.diffPHID', $diff_phid);
Defensive patterns

Strategy: validation

Validate before calling

// Verify the diff property resolves before land executes:
$diff_phid = $operation->getProperty('differential.diffPHID');
if (!$diff_phid) {
  // operation was created without a diff binding; re-create it
}
$diff = id(new DifferentialDiffQuery())
  ->setViewer($operation->getAuthor())
  ->withPHIDs(array($diff_phid))
  ->executeOne();
if (!$diff) {
  // fail fast with a clear message instead of the land exception
}

Try / catch

catch (Exception $ex) { on 'Unable to load diff', check whether differential.diffPHID is empty (bad creation) vs set-but-unloadable (deleted/permissions); cancel the operation in the first case, re-request land in the second }

Prevention

When it happens

Trigger: Operation rows created without the differential.diffPHID property (custom creation code); the diff record being garbage-collected or removed before the operation executes; viewer permission loss on the diff's revision.

Common situations: Long land queues where the revision was updated and old diffs pruned; restoring operations from backup into a database missing the diff rows; extensions queueing land operations without copying the diff PHID.

Related errors


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