phacility/phabricator · error · Exception

Credential has invalid type "%s"!

Error message

Credential has invalid type "%s"!

What it means

Thrown by PassphraseCredentialLockController when the lock workflow (/K<id>/lock) loads a credential whose stored type constant does not resolve to an installed PassphraseCredentialType implementation. The controller needs the type to render the lock confirmation dialog, so an orphaned type constant aborts immediately with an uncaught exception. Like its siblings, it formats the null $type instead of the actual constant.

Source

Thrown at src/applications/passphrase/controller/PassphraseCredentialLockController.php:26

    $id = $request->getURIData('id');

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

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

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

    if ($credential->getIsLocked()) {
      return $this->newDialog()
        ->setTitle(pht('Credential Already Locked'))
        ->appendChild(
          pht('This credential is already locked.'))
        ->addCancelButton($view_uri, pht('Close'));
    }

    if ($request->isFormPost()) {
      $xactions = array();

      $xactions[] = id(new PassphraseCredentialTransaction())
        ->setTransactionType(
          PassphraseCredentialConduitTransaction::TRANSACTIONTYPE)

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Identify the stored constant via $credential->getCredentialType() and compare with registered types.
  2. Reinstall or re-enable the extension providing that constant.
  3. Otherwise remove or archive the orphaned credential row.
Defensive patterns

Strategy: validation

Validate before calling

$all = PassphraseCredentialType::getAllTypes();
if (empty($all[$credential->getCredentialType()])) {
  // do not link or follow /lock: restore the extension or archive the credential
}

Type guard

function credential_type_is_installed($credential) {
  $all = PassphraseCredentialType::getAllTypes();
  return isset($all[$credential->getCredentialType()]);
}

Try / catch

try {
  $type = PassphraseCredentialType::getTypeByConstant(
    $credential->getCredentialType());
} catch (Exception $ex) {
  // hide the lock action and report the orphaned constant
}

Prevention

When it happens

Trigger: Requesting /K<id>/lock for a credential created by an extension that has since been uninstalled, renamed, or failed to load.

Common situations: Post-upgrade cleanup after disabling a custom credential type provider; database migration between installs with different extension sets.

Related errors


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