phacility/phabricator · error · Exception

Credential has no public key!

Error message

Credential has no public key!

What it means

Thrown by PassphraseCredentialPublicController when the credential's type implementation returns false from hasPublicKey(). Only key-like types (SSH keys, certificates) can expose a public component; password, token, and other secret types have no public view at all, so the /K<id>/public page rejects them before calling getPublicKey().

Source

Thrown at src/applications/passphrase/controller/PassphraseCredentialPublicController.php:29

      ->setViewer($viewer)
      ->withIDs(array($id))
      ->requireCapabilities(
        array(
          PhabricatorPolicyCapability::CAN_VIEW,
        ))
      ->executeOne();
    if (!$credential) {
      return new Aphront404Response();
    }

    $type = PassphraseCredentialType::getTypeByConstant(
      $credential->getCredentialType());
    if (!$type) {
      throw new Exception(pht('Credential has invalid type "%s"!', $type));
    }

    if (!$type->hasPublicKey()) {
      throw new Exception(pht('Credential has no public key!'));
    }

    $view_uri = '/'.$credential->getMonogram();

    $public_key = $type->getPublicKey($viewer, $credential);

    $body = id(new PHUIFormLayoutView())
      ->appendChild(
        id(new AphrontFormTextAreaControl())
          ->setLabel(pht('Public Key'))
          ->setReadOnly(true)
          ->setValue($public_key));

    return $this->newDialog()
      ->setWidth(AphrontDialogView::WIDTH_FORM)
      ->setTitle(pht('Public Key (%s)', $credential->getMonogram()))
      ->appendChild($body)
      ->addCancelButton($view_uri, pht('Done'));

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Only render/expose the public-key link when $type->hasPublicKey() is true.
  2. For non-key credentials, use the appropriate workflow (secret reveal under high security, or the type's own views).
  3. Hide the action in menus and object lists rather than letting the page throw.

Example fix

// before
$items[] = id(new PHUIListItemView())
  ->setHref('/K'.$credential->getID().'/public')
  ->setName(pht('Public Key'));

// after
$type = $credential->getImplementation();
if ($type && $type->hasPublicKey()) {
  $items[] = id(new PHUIListItemView())
    ->setHref('/K'.$credential->getID().'/public')
    ->setName(pht('Public Key'));
}
Defensive patterns

Strategy: validation

Validate before calling

$type = PassphraseCredentialType::getTypeByConstant(
  $credential->getCredentialType());
if (!$type || !$type->hasPublicKey()) {
  // do not link or route to /K<id>/public
}

Type guard

function credential_has_public_key($credential) {
  $type = $credential->getImplementation();
  return $type !== null && $type->hasPublicKey();
}

Try / catch

try {
  $public_key = $type->getPublicKey($viewer, $credential);
} catch (Exception $ex) {
  // wrong credential kind: prompt for a key-type credential
}

Prevention

When it happens

Trigger: Navigating to /K<id>/public for a password, API-token, or other non-key credential; templates or menus that unconditionally link the 'Public Key' action for every credential.

Common situations: UI code assuming every credential has a public view; scripts scraping the public-key page for all credentials in an install; users hand-entering the URL.

Related errors


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