phacility/phabricator · error · Exception
Unable to load Duo API credential ("%s").
Error message
Unable to load Duo API credential ("%s"). What it means
PhabricatorDuoAuthFactor::newDuoFuture() resolves the provider property 'duo.credentialPHID' through PassphraseCredentialQuery with the omnipotent user and needSecrets(true). If no Passphrase credential with that PHID exists (deleted, destroyed, or the property references nothing valid), the factor cannot build a Duo API future and throws before any API call. Every Duo operation for that provider (enrollment, preauth, challenge) then fails.
Source
Thrown at src/applications/auth/factor/PhabricatorDuoAuthFactor.php:733
->setIcon('fa-refresh', 'green ph-spin'));
}
return $result;
}
private function newDuoFuture(PhabricatorAuthFactorProvider $provider) {
$credential_phid = $provider->getAuthFactorProviderProperty(
self::PROP_CREDENTIAL);
$omnipotent = PhabricatorUser::getOmnipotentUser();
$credential = id(new PassphraseCredentialQuery())
->setViewer($omnipotent)
->withPHIDs(array($credential_phid))
->needSecrets(true)
->executeOne();
if (!$credential) {
throw new Exception(
pht(
'Unable to load Duo API credential ("%s").',
$credential_phid));
}
$duo_key = $credential->getUsername();
$duo_secret = $credential->getSecret();
if (!$duo_secret) {
throw new Exception(
pht(
'Duo API credential ("%s") has no secret key.',
$credential_phid));
}
$duo_host = $provider->getAuthFactorProviderProperty(
self::PROP_HOSTNAME);
self::requireDuoAPIHostname($duo_host);
View on GitHub (pinned to 5720a38cfe)
Solutions
- Open Auth > Multi-Factor Auth, edit the Duo provider, and select an existing, non-destroyed Passphrase credential (username = Duo integration key, secret = Duo secret key).
- If the original credential was destroyed, create a new password-type credential with both keys and re-select it on the provider.
- After saving, verify by starting a test enrollment or issuing a Duo challenge.
- Audit other MFA providers for references to the same deleted credential.
Defensive patterns
Strategy: validation
Validate before calling
// Run when saving the provider config, not at login time.
$phid = $provider->getAuthFactorProviderProperty(
PhabricatorDuoAuthFactor::PROP_CREDENTIAL);
$exists = (bool) id(new PassphraseCredentialQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($phid))
->withIsDestroyed(false)
->executeOne();
if (!$exists) {
// block the save with a config error naming the missing credential
} Try / catch
try {
$future = $factor->newDuoFuture($provider);
} catch (Exception $ex) {
// surface 'provider misconfigured' to admins and skip this provider
// rather than hard-failing every MFA login
throw new PhutilProxyException(
pht('Duo provider is misconfigured, check its credential.'),
$ex);
} Prevention
- Never delete a Passphrase credential an MFA provider references; rename or rotate instead.
- Re-select the credential on the provider immediately after any rotation.
- Validate the credential PHID (exists, not destroyed) when saving factor provider config.
- Keep one Duo credential per provider and document the linkage.
When it happens
Trigger: Any Duo API operation on a provider whose stored credential PHID no longer resolves: the Passphrase credential was deleted or destroyed, the auth_factor_provider row was hand-edited or restored from a partial dump, or the provider was created against a credential that was later removed.
Common situations: Admin deletes or rotates the old Duo credential in Passphrase before re-pointing the MFA provider; partial database restore loses the passphrase_credential row; scripting provider properties directly instead of using the edit UI.
Related errors
- Duo API credential ("%s") has no secret key.
- Duo username pairing mode ("%s") is not supported.
- Duo enrollment mode ("%s") is not supported.
- Duo API hostname ("%s") is invalid, hostname must be "*.duos
- This Duo enrollment attempt is invalid or has expired ("%s")
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/37d0e19d609f377a.
Report an issue: GitHub.