{"record":{"id":"46c44b333b1ffbb7","repo":"phacility/phabricator","slug":"credential-s-must-provide-s-but-provides","errorCode":null,"errorMessage":"Credential \"%s\" must provide \"%s\", but provides \"%s\"!","messagePattern":"Credential \"(.+?)\" must provide \"(.+?)\", but provides \"(.+?)\"!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/passphrase/keys/PassphraseAbstractKey.php","lineNumber":46,"sourceCode":"    return $credential;\n  }\n\n  private function validateCredential(\n    PassphraseCredential $credential,\n    $provides_type) {\n\n    $type = $credential->getImplementation();\n\n    if (!$type) {\n      throw new Exception(\n        pht(\n          'Credential \"%s\" is of unknown type \"%s\"!',\n          $credential->getMonogram(),\n          $credential->getCredentialType()));\n    }\n\n    if ($type->getProvidesType() !== $provides_type) {\n      throw new Exception(\n        pht(\n          'Credential \"%s\" must provide \"%s\", but provides \"%s\"!',\n          $credential->getMonogram(),\n          $provides_type,\n          $type->getProvidesType()));\n    }\n  }\n\n  protected function loadAndValidateFromPHID(\n    $phid,\n    PhabricatorUser $viewer,\n    $type) {\n\n    $credential = $this->loadCredential($phid, $viewer);\n\n    $this->validateCredential($credential, $type);\n\n    $this->credential = $credential;","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/passphrase/keys/PassphraseAbstractKey.php#L28-L64","documentation":"Thrown by PassphraseAbstractKey::validateCredential() when the credential's implementation provides a different capability than the caller requested: $type->getProvidesType() !== $provides_type. Credential types advertise what they provide ('ssh-key', 'token', 'password', ...), and consumers like PassphraseSSHKey require a specific provides-type, so handing a password or token credential to an SSH-key helper fails before any secret is opened.","triggerScenarios":"Passing a password/token credential PHID to PassphraseSSHKey::loadFromPHID(), which validates against an SSH private-key provides type; wiring a generic token credential into a workflow that only understands SSH keys (e.g. Drydock SSH/working-copy blueprints).","commonSituations":"Configuration UIs that let users pick any credential instead of filtering by provides type; copying a PHID from an unrelated form field; blueprint templates reused across credential kinds.","solutions":["Create a credential of the correct kind (e.g. an 'SSH Private Key' credential) and reference its PHID instead.","Filter credential chooser UIs by provides type so only compatible credentials are offered.","If you implement a consumer, pass the PROVIDES_TYPE constant of the type you can actually consume."],"exampleFix":"// before\n$key = PassphraseSSHKey::loadFromPHID($password_credential_phid, $viewer);\n\n// after\n$credential = id(new PassphraseCredentialQuery())\n  ->setViewer($viewer)\n  ->withPHIDs(array($phid))\n  ->executeOne();\nif ($credential->getImplementation()->getProvidesType() !==\n    PassphraseSSHPrivateKeyCredentialType::PROVIDES_TYPE) {\n  throw new Exception(\n    pht('This workflow requires an SSH private key credential.'));\n}\n$key = PassphraseSSHKey::loadFromPHID($phid, $viewer);","handlingStrategy":"validation","validationCode":"$credential = id(new PassphraseCredentialQuery())\n  ->setViewer($viewer)\n  ->withPHIDs(array($phid))\n  ->executeOne();\nif (!$credential ||\n    $credential->getImplementation()->getProvidesType() !==\n    PassphraseSSHPrivateKeyCredentialType::PROVIDES_TYPE) {\n  // require an SSH-key credential instead\n}","typeGuard":"function credential_provides($credential, $provides_type) {\n  $type = $credential->getImplementation();\n  return $type !== null && $type->getProvidesType() === $provides_type;\n}","tryCatchPattern":"try {\n  $key = PassphraseSSHKey::loadFromPHID($phid, $viewer);\n} catch (Exception $ex) {\n  if (preg_match('/must provide/', $ex->getMessage())) {\n    // prompt user to select an SSH private key credential\n  }\n}","preventionTips":["Filter every credential chooser by the provides type the workflow consumes.","Store provides-type expectations next to configuration that accepts credential PHIDs.","Name credentials by kind (e.g. 'repo-ssh-key') so mismatches are obvious."],"tags":["phabricator","passphrase","credentials","ssh","type-mismatch"],"backgroundTag":"credential-type-mismatch","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}