phacility/phabricator · error · ConduitException

ERR_NOT_FOUND

ERR_NOT_FOUND

Error message

ERR_NOT_FOUND

What it means

Thrown by the differential.closerevision Conduit method. It runs a viewer-policy-filtered DifferentialRevisionQuery (with reviewers attached) on the revisionID parameter, then applies a DifferentialRevisionCloseTransaction through DifferentialTransactionEditor. If the query returns no revision (the ID does not exist or the acting user cannot see it), ConduitException('ERR_NOT_FOUND') is thrown before any transaction is applied.

Source

Thrown at src/applications/differential/conduit/DifferentialCloseConduitAPIMethod.php:50

  }

  protected function defineErrorTypes() {
    return array(
      'ERR_NOT_FOUND' => pht('Revision was not found.'),
    );
  }

  protected function execute(ConduitAPIRequest $request) {
    $viewer = $request->getUser();
    $id = $request->getValue('revisionID');

    $revision = id(new DifferentialRevisionQuery())
      ->withIDs(array($id))
      ->setViewer($viewer)
      ->needReviewers(true)
      ->executeOne();
    if (!$revision) {
      throw new ConduitException('ERR_NOT_FOUND');
    }

    $xactions = array();
    $xactions[] = id(new DifferentialTransaction())
      ->setTransactionType(
        DifferentialRevisionCloseTransaction::TRANSACTIONTYPE)
      ->setNewValue(true);

    $content_source = $request->newContentSource();

    $editor = id(new DifferentialTransactionEditor())
      ->setActor($viewer)
      ->setContentSource($request->newContentSource())
      ->setContinueOnMissingFields(true)
      ->setContinueOnNoEffect(true);

    $editor->applyTransactions($revision, $xactions);

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Pass revisionID as the bare integer ID (123), not 'D123' and not a PHID
  2. Confirm the revision exists and is visible to the same token by calling differential.query with ids=[id] first
  3. Check the revision's view policy and space in the web UI, and run the call with a token from a user who can see it
  4. In automation, treat ERR_NOT_FOUND as non-fatal: log it and continue instead of aborting the whole hook

Example fix

// before
$client->callMethodSynchronous('differential.closerevision', array(
  'revisionID' => 'D123',
));

// after
$client->callMethodSynchronous('differential.closerevision', array(
  'revisionID' => 123,
));
Defensive patterns

Strategy: try-catch

Validate before calling

// PHP conduit client: confirm visibility with the same token first.
$found = $client->callMethodSynchronous(
  'differential.query',
  array('ids' => array((int)$id)));
if (!$found) {
  // nothing to close; skip
  return;
}

Try / catch

try {
  $client->callMethodSynchronous('differential.closerevision',
    array('revisionID' => (int)$id));
} catch (ConduitClientException $ex) {
  if ($ex->getErrorCode() === 'ERR_NOT_FOUND') {
    // revision absent or invisible: log, continue
  } else {
    throw $ex;
  }
}

Prevention

When it happens

Trigger: Calling conduit method differential.closerevision with a revisionID that does not exist, passing 'D123' or a PHID instead of the bare integer, passing null/0, or closing a revision hidden from the caller by object or space visibility policy.

Common situations: Post-merge automation that closes revisions using IDs scraped from commit messages; bot accounts whose conduit token belongs to a user without visibility on the revision; typos when transcribing revision numbers; the revision was deleted after its ID was captured.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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