phacility/phabricator · error · Exception

Unable to load API token

Error message

Unable to load API token ("%s")!

What it means

The CircleCI step stores an API token as a Passphrase credential PHID in its 'token' setting. During execution it loads that credential with PassphraseCredentialQuery (viewer = omnipotent user, needSecrets(true)) and throws when executeOne() returns nothing. Because the viewer is omnipotent, visibility rules are not the cause: the credential PHID is null (step never configured), or the credential no longer loads (deleted, destroyed, or its secret is unavailable).

Solutions

  1. Edit the build step in Harbormaster and select a valid Passphrase credential of type 'Token' that provides a token.
  2. If no credential exists, create one in Passphrase containing a CircleCI API token, then re-select it in the step.
  3. Search other build plans for the deleted PHID (harbormaster_buildstep.settings) and update every step that references it.
  4. If the step was created programmatically, re-create it with the 'token' setting populated.
Defensive patterns

Strategy: validation

Validate before calling

// Verify the step's credential loads (with secrets) before starting builds:
$phid = $step->getSetting('token');
$ok = (bool)id(new PassphraseCredentialQuery())
  ->setViewer(PhabricatorUser::getOmnipotentUser())
  ->withPHIDs(array($phid))
  ->needSecrets(true)
  ->executeOne();
if (!$ok) {
  // credential missing or unusable - fix the step before building
}

Prevention

When it happens

Trigger: Running a build whose CircleCI step has an empty/unset 'token' field, or whose selected credential was deleted from Passphrase afterwards. Also occurs when a plan exported/imported between instances keeps a stale credential PHID, or when the credential is of the wrong type so it is excluded by the query.

Common situations: Someone cleaned up Passphrase credentials while build plans still referenced them; the step was created via Conduit/CLI without the required 'token' field; the credential was created as a non-token type (the field expects PassphraseTokenCredentialType).

Related errors


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

Appendix: source

Thrown at src/applications/harbormaster/step/HarbormasterCircleCIBuildStepImplementation.php:142

          'Object ("%s") claims "%s" is a GitHub repository URI, but the '.
          'path ("%s") does not have enough components (expected at least '.
          'two).',
          $object_phid,
          $github_uri,
          $path));
    }

    list($github_namespace, $github_name) = $path_parts;
    $github_name = preg_replace('(\\.git$)', '', $github_name);

    $credential_phid = $this->getSetting('token');
    $api_token = id(new PassphraseCredentialQuery())
      ->setViewer($viewer)
      ->withPHIDs(array($credential_phid))
      ->needSecrets(true)
      ->executeOne();
    if (!$api_token) {
      throw new Exception(
        pht(
          'Unable to load API token ("%s")!',
          $credential_phid));
    }

    // When we pass "revision", the branch is ignored (and does not even need
    // to exist), and only shows up in the UI. Use a cute string which will
    // certainly never break anything or cause any kind of problem.
    $ship = "\xF0\x9F\x9A\xA2";
    $branch = "{$ship}Harbormaster";

    $token = $api_token->getSecret()->openEnvelope();
    $parts = array(
      'https://circleci.com/api/v1/project',
      phutil_escape_uri($github_namespace),
      phutil_escape_uri($github_name)."?circle-token={$token}",
    );

View on GitHub (pinned to 5720a38cfe)