phacility/phabricator · error · ConduitException

ERR_NOT_FOUND

ERR_NOT_FOUND

Error message

ERR_NOT_FOUND

What it means

Thrown by the differential.getcommitmessage Conduit method. When the revision_id parameter is truthy, the method loads that revision (policy-filtered, with reviewers and active diffs) to render its commit message; if no revision matches, ConduitException('ERR_NOT_FOUND') is thrown. When revision_id is empty the method instead builds a template from a fresh revision, so the error only occurs in the lookup branch.

Source

Thrown at src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php:46

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

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

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

    // There are three modes here: "edit", "create", and "read" (which has
    // no value for the "edit" parameter).

    // In edit or create mode, we hide read-only fields. In create mode, we
    // show "Field:" templates for some fields even if they are empty.
    $edit_mode = $request->getValue('edit');

    $is_any_edit = $edit_mode !== null && (bool)strlen($edit_mode);
    $is_create = ($edit_mode == 'create');

    $field_list = DifferentialCommitMessageField::newEnabledFields($viewer);

    $custom_storage = $this->loadCustomFieldStorage($viewer, $revision);

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Send revision_id as a bare integer that you verified with differential.query
  2. For new revisions, omit revision_id and use the create/edit template modes instead
  3. Ensure the conduit token's user can see the revision
  4. Catch ERR_NOT_FOUND and skip message generation for that ID

Example fix

// before
$params = array(
  'revision_id' => 'D12',
  'edit' => true,
);

// after
$params = array(
  'revision_id' => 12,
  'edit' => true,
);
Defensive patterns

Strategy: try-catch

Validate before calling

if ($rev_id) {
  $found = $client->callMethodSynchronous('differential.query',
    array('ids' => array((int)$rev_id)));
  if (!$found) {
    $rev_id = null; // fall back to template mode for new revisions
  }
}

Try / catch

try {
  $msg = $client->callMethodSynchronous('differential.getcommitmessage',
    array('revision_id' => (int)$rev_id, 'edit' => true));
} catch (ConduitClientException $ex) {
  if ($ex->getErrorCode() === 'ERR_NOT_FOUND') {
    // unknown/invisible revision: skip message rendering
  } else {
    throw $ex;
  }
}

Prevention

When it happens

Trigger: Calling differential.getcommitmessage with a nonexistent revision_id, a 'D'-prefixed string, or an ID invisible to the caller's policy; also edit=true flows where arc tries to fetch a message for an ID that was never uploaded.

Common situations: arc workflows referencing a revision number from an unpushed or deleted branch; scripts generating commit messages in bulk where some revisions were removed; tokens lacking space visibility.

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/2e6941a969ac84cc. Report an issue: GitHub.