{"record":{"id":"509d3c2df98bc25a","repo":"phacility/phabricator","slug":"capability-s-has-invalid-policy-s","errorCode":null,"errorMessage":"Capability \"%s\" has invalid policy \"%s\".","messagePattern":"Capability \"(.+?)\" has invalid policy \"(.+?)\"\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/policy/config/PolicyLockOptionType.php","lineNumber":30,"sourceCode":"    $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));\n        }\n      }\n\n      if ($policy == PhabricatorPolicies::POLICY_PUBLIC) {\n        if (!$capability->shouldAllowPublicPolicySetting()) {\n          throw new Exception(\n            pht(\n              'Capability \"%s\" does not support public policy.',\n              $capability_key));\n        }\n      }\n    }\n\n    if ($policy_phids) {","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/policy/config/PolicyLockOptionType.php#L12-L48","documentation":"Each value in policy.lock must be either a concrete object PHID (phid_get_type recognizes it) or a global policy constant that PhabricatorPolicyQuery::getGlobalPolicy() accepts, such as 'public', 'users', 'admin' or 'no-one'. Anything else fails validation, and the catch block around getGlobalPolicy() rethrows with this clearer message naming the capability and the invalid policy value.","triggerScenarios":"Saving policy.lock with a value like 'everybody', 'all-users', 'members', or a malformed PHID-like string: not a valid PHID type and not a known global policy constant.","commonSituations":"Guessing constant names instead of checking the PhabricatorPolicies class; configs migrated from other tools with different policy vocabulary; trailing whitespace or case changes in hand-edited JSON.","solutions":["Use the exact global policy constants from the PhabricatorPolicies class, or a real object PHID","Copy values from the policy chooser in the UI, whose options correspond to the valid inputs","Fix the single offending value named in the error message and re-save"],"exampleFix":"// before: not a global policy constant nor a PHID\n{\"diffusion.push\": \"all\"}\n\n// after: valid global policy constant\n{\"diffusion.push\": \"users\"}","handlingStrategy":"validation","validationCode":"// Validate each policy value before saving policy.lock.\n$is_phid = phid_get_type($policy) !== PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN;\n$is_global = in_array($policy, array('public', 'users', 'admin', 'no-one'), true);\nif (!$is_phid && !$is_global) {\n  throw new Exception(pht('Invalid policy value: %s', $policy));\n}","typeGuard":"function isValidPolicyValue($policy) {\n  if (!is_string($policy) || $policy === '') {\n    return false;\n  }\n  if (phid_get_type($policy) !== PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {\n    return true;\n  }\n  try {\n    PhabricatorPolicyQuery::getGlobalPolicy($policy);\n    return true;\n  } catch (Exception $ex) {\n    return false;\n  }\n}","tryCatchPattern":null,"preventionTips":["Source policy values from PhabricatorPolicies constants, never free text","Validate configs in review tooling before they reach production","Watch for casing and whitespace when editing JSON by hand"],"tags":["phabricator","config","policy","policy-lock","validation"],"backgroundTag":"invalid-config-value","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}