phacility/phabricator · error · Exception

Capability "%s" has invalid policy "%s".

Error message

Capability "%s" has invalid policy "%s".

What it means

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.

Source

Thrown at src/applications/policy/config/PolicyLockOptionType.php:30

    $policy_phids = array();
    foreach ($value as $capability_key => $policy) {
      $capability = idx($capabilities, $capability_key);
      if (!$capability) {
        throw new Exception(
          pht(
            'Capability "%s" does not exist.',
            $capability_key));
      }
      if (phid_get_type($policy) !=
          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) {

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Use the exact global policy constants from the PhabricatorPolicies class, or a real object PHID
  2. Copy values from the policy chooser in the UI, whose options correspond to the valid inputs
  3. Fix the single offending value named in the error message and re-save

Example fix

// before: not a global policy constant nor a PHID
{"diffusion.push": "all"}

// after: valid global policy constant
{"diffusion.push": "users"}
Defensive patterns

Strategy: validation

Validate before calling

// Validate each policy value before saving policy.lock.
$is_phid = phid_get_type($policy) !== PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN;
$is_global = in_array($policy, array('public', 'users', 'admin', 'no-one'), true);
if (!$is_phid && !$is_global) {
  throw new Exception(pht('Invalid policy value: %s', $policy));
}

Type guard

function isValidPolicyValue($policy) {
  if (!is_string($policy) || $policy === '') {
    return false;
  }
  if (phid_get_type($policy) !== PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {
    return true;
  }
  try {
    PhabricatorPolicyQuery::getGlobalPolicy($policy);
    return true;
  } catch (Exception $ex) {
    return false;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/509d3c2df98bc25a. Report an issue: GitHub.