{"record":{"id":"a95e48cb33986ba4","repo":"phacility/phabricator","slug":"capability-s-does-not-exist","errorCode":null,"errorMessage":"Capability \"%s\" does not exist.","messagePattern":"Capability \"(.+?)\" does not exist\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/policy/config/PolicyLockOptionType.php","lineNumber":16,"sourceCode":"<?php\n\nfinal class PolicyLockOptionType\n  extends PhabricatorConfigJSONOptionType {\n\n  public function validateOption(PhabricatorConfigOption $option, $value) {\n    $capabilities = id(new PhutilClassMapQuery())\n      ->setAncestorClass('PhabricatorPolicyCapability')\n      ->setUniqueMethod('getCapabilityKey')\n      ->execute();\n\n    $policy_phids = array();\n    foreach ($value as $capability_key => $policy) {\n      $capability = idx($capabilities, $capability_key);\n      if (!$capability) {\n        throw new Exception(\n          pht(\n            'Capability \"%s\" does not exist.',\n            $capability_key));\n      }\n      if (phid_get_type($policy) !=\n          PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {\n        $policy_phids[$policy] = $policy;\n      } else {\n        try {\n          $policy_object = PhabricatorPolicyQuery::getGlobalPolicy($policy);\n        // this exception is not helpful here as its about global policy;\n        // throw a better exception\n        } catch (Exception $ex) {\n          throw new Exception(\n            pht(\n              'Capability \"%s\" has invalid policy \"%s\".',\n              $capability_key,\n              $policy));","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/policy/config/PolicyLockOptionType.php#L1-L34","documentation":"policy.lock is a JSON config option that force-locks object policies per capability. PolicyLockOptionType::validateOption() expands every PhabricatorPolicyCapability subclass into a key map and rejects any key in the JSON that is not a registered capability key. The whole config write is refused, keeping the lock set consistent with installed capability classes.","triggerScenarios":"Saving policy.lock containing a capability key no PhabricatorPolicyCapability subclass provides: a typo, a key removed by an upgrade, or a key defined by an extension that is no longer installed.","commonSituations":"Copy-pasting config between instances with different extensions installed; upgrading Phabricator where a capability was renamed or retired; hand-editing the policy.lock JSON.","solutions":["Remove or correct the unknown capability key in the policy.lock configuration","Enumerate valid keys by listing PhabricatorPolicyCapability subclasses (or the policy UI pickers) and use exactly those strings","Re-validate saved policy.lock values after upgrades, since retired keys only surface on the next save"],"exampleFix":"// before: unknown capability key rejects the whole config\n{\"maniphest.priorities\": \"admin\"}\n\n// after: use a capability key that actually exists\n{\"diffusion.push\": \"admin\"}","handlingStrategy":"validation","validationCode":"// Validate policy.lock keys before saving.\n$capabilities = id(new PhutilClassMapQuery())\n  ->setAncestorClass('PhabricatorPolicyCapability')\n  ->setUniqueMethod('getCapabilityKey')\n  ->execute();\nforeach ($value as $capability_key => $_) {\n  if (empty($capabilities[$capability_key])) {\n    throw new Exception(pht('Unknown capability key: %s', $capability_key));\n  }\n}","typeGuard":"function isKnownPolicyCapability($key) {\n  static $keys;\n  if ($keys === null) {\n    $keys = id(new PhutilClassMapQuery())\n      ->setAncestorClass('PhabricatorPolicyCapability')\n      ->setUniqueMethod('getCapabilityKey')\n      ->execute();\n  }\n  return isset($keys[$key]);\n}","tryCatchPattern":null,"preventionTips":["Lint policy.lock keys against installed capabilities in CI for config-as-code setups","Re-validate lock configs after every Phabricator upgrade or extension change","Never hand-type capability keys; copy them from the policy UI or class constants"],"tags":["phabricator","config","policy","policy-lock","validation"],"backgroundTag":"unknown-config-key","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}