phacility/phabricator · error · Exception
Capability "%s" does not support public policy.
Error message
Capability "%s" does not support public policy.
What it means
policy.lock may set the value 'public' (PhabricatorPolicies::POLICY_PUBLIC) only on capabilities whose implementation opts in by overriding shouldAllowPublicPolicySetting(). Most capabilities contain user-submitted data and do not opt in, so locking them to public is rejected during config validation.
Source
Thrown at src/applications/policy/config/PolicyLockOptionType.php:40
PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {
$policy_phids[$policy] = $policy;
} else {
try {
$policy_object = PhabricatorPolicyQuery::getGlobalPolicy($policy);
// this exception is not helpful here as its about global policy;
// throw a better exception
} catch (Exception $ex) {
throw new Exception(
pht(
'Capability "%s" has invalid policy "%s".',
$capability_key,
$policy));
}
}
if ($policy == PhabricatorPolicies::POLICY_PUBLIC) {
if (!$capability->shouldAllowPublicPolicySetting()) {
throw new Exception(
pht(
'Capability "%s" does not support public policy.',
$capability_key));
}
}
}
if ($policy_phids) {
$handles = id(new PhabricatorHandleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPhids($policy_phids)
->execute();
$handles = mpull($handles, null, 'getPHID');
foreach ($value as $capability_key => $policy) {
$handle = $handles[$policy];
if (!$handle->isComplete()) {
throw new Exception(
pht(View on GitHub (pinned to 5720a38cfe)
Solutions
- Use 'users' or another permitted policy value for that capability
- Verify the capability genuinely advertises public support before attempting to lock it to public
- Keep per-capability defaults from the policy UI as the source of truth for which values are acceptable
Example fix
// before: capability does not allow public policy
{"diffusion.push": "public"}
// after: use a supported policy value
{"diffusion.push": "users"} Defensive patterns
Strategy: validation
Validate before calling
// Reject public locks on capabilities that do not allow them.
if ($policy === PhabricatorPolicies::POLICY_PUBLIC) {
if (!$capability->shouldAllowPublicPolicySetting()) {
// fall back to an allowed policy such as POLICY_USER
$policy = PhabricatorPolicies::POLICY_USER;
}
} Type guard
function capabilityAllowsPublic(PhabricatorPolicyCapability $capability) {
return $capability->shouldAllowPublicPolicySetting();
} Prevention
- Default to 'users' when locking policies; only use 'public' where the capability explicitly opts in
- Review shouldAllowPublicPolicySetting() on the target capability before writing the config
- Keep public-policy exceptions documented per capability so configs are auditable
When it happens
Trigger: The policy.lock JSON assigns the string 'public' to a capability whose PhabricatorPolicyCapability subclass returns false from shouldAllowPublicPolicySetting().
Common situations: Instance admins trying to open everything to anonymous users during initial setup; copying a public-heavy config onto capabilities that never supported public policy.
Related errors
- Capability "%s" does not exist.
- Capability "%s" has invalid policy "%s".
- You can not accept this commit because you are the commit au
- Capability "%s" has invalid policy "%s"; "%s" does not exist
- Config option "phd.user" is not set. You must set this optio
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/8f08dca5cf2a9903.
Report an issue: GitHub.