{"record":{"id":"81678e772d9db5d1","repo":"phacility/phabricator","slug":"credential-has-noncreateable-type-s","errorCode":null,"errorMessage":"Credential has noncreateable type \"%s\"!","messagePattern":"Credential has noncreateable type \"(.+?)\"!","errorType":"exception","errorClass":"Exception","httpStatus":500,"severity":"error","filePath":"src/applications/passphrase/controller/PassphraseCredentialEditController.php","lineNumber":32,"sourceCode":"          array(\n            PhabricatorPolicyCapability::CAN_VIEW,\n            PhabricatorPolicyCapability::CAN_EDIT,\n          ))\n        ->executeOne();\n      if (!$credential) {\n        return new Aphront404Response();\n      }\n\n      $type = $this->getCredentialType($credential->getCredentialType());\n      $type_const = $type->getCredentialType();\n\n      $is_new = false;\n    } else {\n      $type_const = $request->getStr('type');\n      $type = $this->getCredentialType($type_const);\n\n      if (!$type->isCreateable()) {\n        throw new Exception(\n          pht(\n            'Credential has noncreateable type \"%s\"!',\n            $type_const));\n      }\n\n      $credential = PassphraseCredential::initializeNewCredential($viewer)\n        ->setCredentialType($type->getCredentialType())\n        ->setProvidesType($type->getProvidesType())\n        ->attachImplementation($type);\n\n      $is_new = true;\n\n      // Prefill username if provided.\n      $credential->setUsername((string)$request->getStr('username'));\n\n      if (!$request->getStr('isInitialized')) {\n        $type->didInitializeNewCredential($viewer, $credential);\n      }","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/passphrase/controller/PassphraseCredentialEditController.php#L14-L50","documentation":"Thrown by PassphraseCredentialEditController when a user tries to create a NEW credential of a type that exists but returns false from isCreateable(). Some credential types are internal: they are minted by other machinery (automation tokens, generated keys) and must not be hand-created through the passphrase create form. Editing an existing credential of such a type is allowed; only manual creation is blocked.","triggerScenarios":"POSTing to /passphrase/edit/ with a 'type' request parameter naming a non-createable implementation; deep-linking the create form with ?type=<internal-constant>.","commonSituations":"A custom PassphraseCredentialType intended only for machine use where the developer forgot users can still reach the create form via the type parameter; links or templates carrying an internal type constant into the create workflow.","solutions":["Pick a user-createable type in the create form (drop the type parameter so the form only lists createable types).","If the type should be manually createable, override isCreateable() to return true in its implementation.","Route users to the workflow that mints the internal credential instead of the generic create form."],"exampleFix":"// before\n$type_const = $request->getStr('type');\n$type = $this->getCredentialType($type_const);\nif (!$type->isCreateable()) {\n  throw new Exception(pht('Credential has noncreateable type \"%s\"!', $type_const));\n}\n\n// after: only offer types that allow manual creation\n$all_types = PassphraseCredentialType::getAllTypes();\n$type = idx($all_types, $request->getStr('type'));\n$createable = mpick(\n  mfilter($all_types, 'isCreateable'),\n  'getCredentialType');\nif (!$type || !isset($createable[$type->getCredentialType()])) {\n  $type = idx($all_types, key($createable));\n}","handlingStrategy":"validation","validationCode":"$createable = mpick(\n  mfilter(PassphraseCredentialType::getAllTypes(), 'isCreateable'),\n  'getCredentialType');\nif (!isset($createable[$requested_const])) {\n  $requested_const = null; // fall back to the default createable type\n}","typeGuard":"function is_createable_credential_type($type_const) {\n  $createable = mpick(\n    mfilter(PassphraseCredentialType::getAllTypes(), 'isCreateable'),\n    'getCredentialType');\n  return isset($createable[$type_const]);\n}","tryCatchPattern":"try {\n  // create credential of $type_const\n} catch (Exception $ex) {\n  if (preg_match('/noncreateable/', $ex->getMessage())) {\n    // retry with a type selected from isCreateable()-filtered list\n  }\n}","preventionTips":["Build create-form dropdowns only from types where isCreateable() is true.","Ignore or validate the incoming 'type' parameter against that filtered list.","Link internal types to the workflow that mints them, not to the create form."],"tags":["phabricator","passphrase","credentials","validation","acl"],"backgroundTag":"unsupported-credential-type","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}