phacility/phabricator · error · Exception
Invalid action '%s'!
Error message
Invalid action '%s'!
What it means
Every entry in the custom-policy `rules` JSON must carry an `action` that is exactly `allow` or `deny`. The controller switches on idx($rule, 'action'); a missing action (null) or any other value falls into the default branch and throws before the rule is stored. The check runs while folding the posted data into rule_data.
Source
Thrown at src/applications/policy/controller/PhabricatorPolicyEditController.php:107
if ($request->isFormPost()) {
$data = $request->getStr('rules');
try {
$data = phutil_json_decode($data);
} catch (PhutilJSONParserException $ex) {
throw new PhutilProxyException(
pht('Failed to JSON decode rule data!'),
$ex);
}
$rule_data = array();
foreach ($data as $rule) {
$action = idx($rule, 'action');
switch ($action) {
case 'allow':
case 'deny':
break;
default:
throw new Exception(pht("Invalid action '%s'!", $action));
}
$rule_class = idx($rule, 'rule');
if (empty($rules[$rule_class])) {
throw new Exception(pht("Invalid rule class '%s'!", $rule_class));
}
$rule_obj = $rules[$rule_class];
$value = $rule_obj->getValueForStorage(idx($rule, 'value'));
$rule_data[] = array(
'action' => $action,
'rule' => $rule_class,
'value' => $value,
);
}
View on GitHub (pinned to 5720a38cfe)
Solutions
- Give every rule object "action": "allow" or "action": "deny" (lowercase, exact).
- Remove rules that should neither allow nor deny instead of inventing another action value.
- Run the payload through the type guard below before POSTing.
Example fix
// before
[{"rule":"PhabricatorUsersPolicyRule","value":["PHID-USER-xxx"]}]
// after
[{"action":"allow","rule":"PhabricatorUsersPolicyRule","value":["PHID-USER-xxx"]}] Defensive patterns
Strategy: validation
Validate before calling
$valid_actions = array('allow' => true, 'deny' => true);
foreach ($payload as $rule) {
if (empty($valid_actions[idx($rule, 'action')])) {
throw new Exception(pht('Refusing to POST: rule action must be allow or deny.'));
}
} Type guard
function is_valid_policy_action($action) {
return in_array($action, array('allow', 'deny'), true);
} Prevention
- Model `action` as a closed enum in client code; never pass free-text user input into it.
- Validate the whole rules payload in one pass before POSTing (action, rule class, value).
When it happens
Trigger: Posting a rule object without an `action` key, or with a value like "Allow", "grant", true, or null, to the policy edit endpoint.
Common situations: Scripts that assemble rule payloads by hand, client code ported from a different policy dialect, and replayed requests edited in an intercepting proxy.
Related errors
- Invalid rule class '%s'!
- Unable to load file ("%s") for import.
- ERR-INVALID-AUTH
- You do not have permission to push to this repository.
- You can not accept this commit because you are the commit au
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/c68747f79b806d86.
Report an issue: GitHub.