{"record":{"id":"0e688f530d60f1cc","repo":"phacility/phabricator","slug":"credential-has-invalid-type-s-0e688f","errorCode":null,"errorMessage":"Credential has invalid type \"%s\"!","messagePattern":"Credential has invalid type \"(.+?)\"!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/passphrase/controller/PassphraseCredentialLockController.php","lineNumber":26,"sourceCode":"    $id = $request->getURIData('id');\n\n    $credential = id(new PassphraseCredentialQuery())\n      ->setViewer($viewer)\n      ->withIDs(array($id))\n      ->requireCapabilities(\n        array(\n          PhabricatorPolicyCapability::CAN_VIEW,\n          PhabricatorPolicyCapability::CAN_EDIT,\n        ))\n      ->executeOne();\n    if (!$credential) {\n      return new Aphront404Response();\n    }\n\n    $type = PassphraseCredentialType::getTypeByConstant(\n      $credential->getCredentialType());\n    if (!$type) {\n      throw new Exception(pht('Credential has invalid type \"%s\"!', $type));\n    }\n\n    $view_uri = '/K'.$credential->getID();\n\n    if ($credential->getIsLocked()) {\n      return $this->newDialog()\n        ->setTitle(pht('Credential Already Locked'))\n        ->appendChild(\n          pht('This credential is already locked.'))\n        ->addCancelButton($view_uri, pht('Close'));\n    }\n\n    if ($request->isFormPost()) {\n      $xactions = array();\n\n      $xactions[] = id(new PassphraseCredentialTransaction())\n        ->setTransactionType(\n          PassphraseCredentialConduitTransaction::TRANSACTIONTYPE)","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/passphrase/controller/PassphraseCredentialLockController.php#L8-L44","documentation":"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.","triggerScenarios":"Requesting /K<id>/lock for a credential created by an extension that has since been uninstalled, renamed, or failed to load.","commonSituations":"Post-upgrade cleanup after disabling a custom credential type provider; database migration between installs with different extension sets.","solutions":["Identify the stored constant via $credential->getCredentialType() and compare with registered types.","Reinstall or re-enable the extension providing that constant.","Otherwise remove or archive the orphaned credential row."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"$all = PassphraseCredentialType::getAllTypes();\nif (empty($all[$credential->getCredentialType()])) {\n  // do not link or follow /lock: restore the extension or archive the credential\n}","typeGuard":"function credential_type_is_installed($credential) {\n  $all = PassphraseCredentialType::getAllTypes();\n  return isset($all[$credential->getCredentialType()]);\n}","tryCatchPattern":"try {\n  $type = PassphraseCredentialType::getTypeByConstant(\n    $credential->getCredentialType());\n} catch (Exception $ex) {\n  // hide the lock action and report the orphaned constant\n}","preventionTips":["Disable extension-provided credential types only after their credentials are migrated.","Keep extension sets synchronized across environments sharing a DB.","Add a periodic audit comparing stored constants against getAllTypes()."],"tags":["phabricator","passphrase","credentials","lock","extension"],"backgroundTag":"unknown-credential-type","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}