phacility/phabricator · error · PhutilProxyException
Failed to decode rule data.
Error message
Failed to decode rule data.
What it means
Thrown by HeraldRuleController::processRequest when saving a rule: the client POSTs a 'rule' parameter containing the whole rule serialized as JSON, and phutil_json_decode() throws PhutilJSONParserException because the blob is not parseable JSON. The controller wraps it in a PhutilProxyException with this generic message so the underlying parse error (position, reason) travels along with it.
Source
Thrown at src/applications/herald/controller/HeraldRuleController.php:289
// valid policy value.
$repetition_options = $this->getRepetitionOptionMap($adapter);
if (!isset($repetition_options[$repetition_policy])) {
$repetition_policy = head_key($repetition_options);
}
$e_name = true;
$errors = array();
if (!strlen($new_name)) {
$e_name = pht('Required');
$errors[] = pht('Rule must have a name.');
}
$data = null;
try {
$data = phutil_json_decode($request->getStr('rule'));
} catch (PhutilJSONParserException $ex) {
throw new PhutilProxyException(
pht('Failed to decode rule data.'),
$ex);
}
if (!is_array($data) ||
!$data['conditions'] ||
!$data['actions']) {
throw new Exception(pht('Failed to decode rule data.'));
}
$conditions = array();
foreach ($data['conditions'] as $condition) {
if ($condition === null) {
// We manage this as a sparse array on the client, so may receive
// NULL if conditions have been removed.
continue;
}
View on GitHub (pinned to 5720a38cfe)
Solutions
- Save the rule through the standard rule editor UI and let it serialize the payload; do not hand-edit the hidden 'rule' field.
- If scripting the endpoint, build strict JSON (double quotes, no trailing commas) and verify with jq before POSTing.
- Raise PHP post_max_size / upload_max_filesize and any proxy body limits if very large rules are being truncated mid-request.
- Check the wrapped PhutilJSONParserException message (visible in the exception trace/logs) for the exact parse offset, then fix that spot in the payload.
Example fix
// before — posting a PHP-ish blob
curl -d 'rule=conditions=>Array;actions=>Array' .../herald/edit/
// after — post strict JSON matching the client's schema
curl -d 'rule={"name":"Triage","conditions":[["title","contains","fix"]],"actions":[["addcc","alice"]],"logic":[]}' .../herald/edit/ Defensive patterns
Strategy: try-catch
Validate before calling
// Server-side pre-flight of the client payload
$raw = $request->getStr('rule');
try {
$data = phutil_json_decode($raw);
} catch (PhutilJSONParserException $ex) {
// return a 400 dialog with $ex->getMessage() (shows parse offset)
} Type guard
function isStrictJson($raw) {
if (!is_string($raw) || $raw === '') {
return false;
}
try {
phutil_json_decode($raw);
return true;
} catch (PhutilJSONParserException $ex) {
return false;
}
} Try / catch
try {
$data = phutil_json_decode($request->getStr('rule'));
} catch (PhutilJSONParserException $ex) {
throw new PhutilProxyException(
pht('Failed to decode rule data.'),
$ex); // preserve the parse position for logs
} Prevention
- Let the standard rule editor serialize the payload; don't hand-craft the hidden field.
- Raise post_max_size and proxy body limits so large rules aren't silently truncated.
- In integrations, validate the serialized blob with jq before POSTing.
When it happens
Trigger: The 'rule' request parameter is truncated, empty, mojibake, or double-encoded when the rule edit form is submitted (Javelin client normally serializes it). Triggered by browser extensions rewriting form bodies, proxies trimming POST data, hand-crafted curl requests with malformed JSON, or client-side bugs that submit before serialization finishes.
Common situations: Scripting or fuzzing the /herald/edit/ endpoint without building the Javelin client's exact JSON payload; request-body size limits (post_max_size, proxy limits) silently truncating large rules with many conditions; ad-hoc integrations that send a PHP-style serialized array instead of JSON.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- The regular expression pair "%s" is not valid JSON. Enter a
- The regular expression pair "%s" must have exactly two eleme
- Invalid JSON input.
- Regular expression pair is not valid JSON!
- Regular expression pair is not a pair!
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/669be015b70c9046.
Report an issue: GitHub.