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

  1. Save the rule through the standard rule editor UI and let it serialize the payload; do not hand-edit the hidden 'rule' field.
  2. If scripting the endpoint, build strict JSON (double quotes, no trailing commas) and verify with jq before POSTing.
  3. Raise PHP post_max_size / upload_max_filesize and any proxy body limits if very large rules are being truncated mid-request.
  4. 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

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

Related errors


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