phacility/phabricator · error · Exception
Failed to load credential "%s"!
Error message
Failed to load credential "%s"!
What it means
Thrown by PassphraseAbstractKey::loadCredential() when a PassphraseCredentialQuery (with needSecrets(true)) for the given PHID returns no result. The query silently collapses three distinct situations into null: the PHID is not a credential at all, the credential row was deleted, or the acting viewer lacks the view policy to see it. The generic 'Failed to load credential' message therefore hides which of the three applies.
Source
Thrown at src/applications/passphrase/keys/PassphraseAbstractKey.php:25
protected function requireCredential() {
if (!$this->credential) {
throw new Exception(pht('Credential is required!'));
}
return $this->credential;
}
private function loadCredential(
$phid,
PhabricatorUser $viewer) {
$credential = id(new PassphraseCredentialQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
->needSecrets(true)
->executeOne();
if (!$credential) {
throw new Exception(pht('Failed to load credential "%s"!', $phid));
}
return $credential;
}
private function validateCredential(
PassphraseCredential $credential,
$provides_type) {
$type = $credential->getImplementation();
if (!$type) {
throw new Exception(
pht(
'Credential "%s" is of unknown type "%s"!',
$credential->getMonogram(),
$credential->getCredentialType()));
}View on GitHub (pinned to 5720a38cfe)
Solutions
- Verify the PHID shape first: phid_get_type($phid) must return 'KREA' (credential).
- Load the credential yourself with PassphraseCredentialQuery as the same viewer to distinguish 'not found' from 'no permission'.
- Update whatever object references the PHID (blueprint, repository, build plan) to point at a live credential.
- If policies are the cause, widen the credential's view policy or run the operation as an empowered actor.
Example fix
// before
$key = PassphraseSSHKey::loadFromPHID($phid, $viewer);
// after
if (!phid_get_type($phid) || phid_get_type($phid) != 'KREA') {
throw new Exception(
pht('Expected a credential PHID, got "%s".', $phid));
}
$exists = id(new PassphraseCredentialQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
->setLimit(1)
->execute();
if (!$exists) {
throw new Exception(
pht(
'Credential "%s" does not exist or is not visible to %s.',
$phid,
$viewer->getUsername()));
}
$key = PassphraseSSHKey::loadFromPHID($phid, $viewer); Defensive patterns
Strategy: validation
Validate before calling
if (!phid_get_type($phid) || phid_get_type($phid) != 'KREA') {
throw new Exception(pht('Expected a credential PHID, got "%s".', $phid));
}
$credential = id(new PassphraseCredentialQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
->setLimit(1)
->execute();
if (!$credential) {
// distinguish deleted vs policy-blocked before proceeding
} Type guard
function is_credential_phid($phid) {
return is_string($phid) && phid_get_type($phid) === 'KREA';
} Try / catch
try {
$key = PassphraseSSHKey::loadFromPHID($phid, $viewer);
} catch (Exception $ex) {
// re-check with an omnipotent query to tell 'deleted' from 'no access'
} Prevention
- Validate PHID shape (type KREA) before any credential-consuming API call.
- When users delete credentials, scan blueprints/repos/build plans for dangling references.
- Run daemons with an actor whose policies can see the credentials they must use.
When it happens
Trigger: Calling PassphraseSSHKey::loadFromPHID()/loadAndValidateFromPHID() with a PHID that is malformed or belongs to another object type; referencing a deleted credential (e.g. from a Drydock blueprint or repository config); running under a daemon/system actor whose policies exclude the credential.
Common situations: Stale credential PHIDs persisted in blueprints, build plans, or working copy configurations after the credential was deleted; passing 'PHID-USER-...' or an object name like 'K123' where a PHID string is expected; daemons running as omnipotent-less actors.
Related errors
- Unable to load API token ("%s")!
- No valid object provided for object rule!
- Credential has invalid type "%s"!
- Credential has invalid type "%s"!
- Credential has noncreateable type "%s"!
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/4180cf66f3a51679.
Report an issue: GitHub.