{"record":{"id":"229be1a750832a7f","repo":"phacility/phabricator","slug":"regular-expression-pair-is-not-valid-json","errorCode":null,"errorMessage":"Regular expression pair is not valid JSON!","messagePattern":"Regular expression pair is not valid JSON!","errorType":"validation","errorClass":"HeraldInvalidConditionException","httpStatus":null,"severity":"error","filePath":"src/applications/herald/adapter/HeraldAdapter.php","lineNumber":560,"sourceCode":"\n            throw new HeraldInvalidConditionException($message);\n          }\n\n          if ($result) {\n            return $result_if_match;\n          }\n        }\n        return !$result_if_match;\n      case self::CONDITION_REGEXP_PAIR:\n        // Match a JSON-encoded pair of regular expressions against a\n        // dictionary. The first regexp must match the dictionary key, and the\n        // second regexp must match the dictionary value. If any key/value pair\n        // in the dictionary matches both regexps, the condition is satisfied.\n        $regexp_pair = null;\n        try {\n          $regexp_pair = phutil_json_decode($condition_value);\n        } catch (PhutilJSONParserException $ex) {\n          throw new HeraldInvalidConditionException(\n            pht('Regular expression pair is not valid JSON!'));\n        }\n        if (count($regexp_pair) != 2) {\n          throw new HeraldInvalidConditionException(\n            pht('Regular expression pair is not a pair!'));\n        }\n\n        $key_regexp   = array_shift($regexp_pair);\n        $value_regexp = array_shift($regexp_pair);\n\n        foreach ((array)$field_value as $key => $value) {\n          $key_matches = @preg_match($key_regexp, $key);\n          if ($key_matches === false) {\n            throw new HeraldInvalidConditionException(\n              pht('First regular expression is invalid!'));\n          }\n          if ($key_matches) {\n            $value_matches = @preg_match($value_regexp, $value);","sourceCodeStart":542,"sourceCodeEnd":578,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/herald/adapter/HeraldAdapter.php#L542-L578","documentation":"The CONDITION_REGEXP_PAIR condition stores a JSON-encoded pair of regular expressions (key regexp, value regexp) to match against dictionary field values. The adapter phutil_json_decode()s the stored condition value; if it is not valid JSON, PhutilJSONParserException is caught and rethrown as HeraldInvalidConditionException('Regular expression pair is not valid JSON!').","triggerScenarios":"A rule with a 'regexp pair' condition whose stored value is a plain string like 'foo,bar' or unquoted/malformed JSON — usually created via the Conduit API or a migration script, since the web editor stores valid JSON.","commonSituations":"herald.rule.edit calls that pass a raw string instead of a JSON-encoded array; hand-edited herald_condition rows; rules imported from another instance with mangled escaping.","solutions":["Set the condition value to a JSON-encoded array of exactly two regexp strings, e.g. json_encode(array('/key-regex/', '/value-regex/')).","Re-save the rule through the Herald UI so the editor rewrites the value in the correct format.","If it keeps recurring, audit whatever script/integration writes the rule value and fix it to emit JSON."],"exampleFix":"// before (stored condition value)\nfoo.*,bar.*\n\n// after\n[\"/foo.*/\", \"/bar.*/\"]","handlingStrategy":"validation","validationCode":"// Pre-validate a regexp-pair condition value before saving:\ntry {\n  $pair = phutil_json_decode($value);\n} catch (PhutilJSONParserException $ex) {\n  $pair = null;\n}\nif (!is_array($pair)) {\n  $value = phutil_json_encode(array('/key-pattern/', '/value-pattern/'));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store regexp-pair values as json_encode(array($keyRegexp, $valueRegexp)).","Re-save API-created regexp-pair rules through the UI once to normalize storage."],"tags":["herald","regex","json","phabricator"],"backgroundTag":"invalid-json-payload","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}