phacility/phabricator · error · HeraldInvalidConditionException
Regular expression pair is not a pair!
Error message
Regular expression pair is not a pair!
What it means
For CONDITION_REGEXP_PAIR, the condition value decoded as JSON but count($regexp_pair) != 2 — the JSON is valid but not a two-element array. The adapter needs exactly one key regexp and one value regexp, so any other length is rejected with HeraldInvalidConditionException before matching begins.
Source
Thrown at src/applications/herald/adapter/HeraldAdapter.php:564
if ($result) {
return $result_if_match;
}
}
return !$result_if_match;
case self::CONDITION_REGEXP_PAIR:
// Match a JSON-encoded pair of regular expressions against a
// dictionary. The first regexp must match the dictionary key, and the
// second regexp must match the dictionary value. If any key/value pair
// in the dictionary matches both regexps, the condition is satisfied.
$regexp_pair = null;
try {
$regexp_pair = phutil_json_decode($condition_value);
} catch (PhutilJSONParserException $ex) {
throw new HeraldInvalidConditionException(
pht('Regular expression pair is not valid JSON!'));
}
if (count($regexp_pair) != 2) {
throw new HeraldInvalidConditionException(
pht('Regular expression pair is not a pair!'));
}
$key_regexp = array_shift($regexp_pair);
$value_regexp = array_shift($regexp_pair);
foreach ((array)$field_value as $key => $value) {
$key_matches = @preg_match($key_regexp, $key);
if ($key_matches === false) {
throw new HeraldInvalidConditionException(
pht('First regular expression is invalid!'));
}
if ($key_matches) {
$value_matches = @preg_match($value_regexp, $value);
if ($value_matches === false) {
throw new HeraldInvalidConditionException(
pht('Second regular expression is invalid!'));
}View on GitHub (pinned to 5720a38cfe)
Solutions
- Store exactly two elements: json_encode(array('/key-regexp/', '/value-regexp/')).
- Re-save the condition in the Herald UI to normalize it.
- Add a count check in whatever automation writes these values before it saves the rule.
Example fix
// before ["/foo.*/", "/bar.*/", "/baz.*/"] // after ["/foo.*/", "/bar.*/"]
Defensive patterns
Strategy: validation
Validate before calling
$pair = phutil_json_decode($value);
if (!is_array($pair) || count($pair) !== 2) {
// fix the stored value: exactly [keyRegexp, valueRegexp]
} Type guard
function isHeraldRegexpPairValue($value) {
try {
$pair = phutil_json_decode($value);
} catch (PhutilJSONParserException $ex) {
return false;
}
return is_array($pair) && count($pair) === 2;
} Prevention
- Emit exactly two elements when generating regexp pairs.
- Add a count check to any script that writes herald_condition values for REGEXP_PAIR.
When it happens
Trigger: A regexp-pair condition value like ["/a/"] (one element), ["/a/", "/b/", "/c/"] (three), or a JSON object/empty array [] — again typically from API-written or migrated rule data rather than the UI.
Common situations: Scripts building pair values by naive string concatenation; edits that append a third pattern; empty array defaults from templates.
Related errors
- Regular expression pair is not valid JSON!
- Regular expression "%s" in Herald rule "%s" is not valid, or
- First regular expression is invalid!
- Second regular expression is invalid!
- The regular expression "%s" is not valid. Regular expression
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/3fbd07485a7dd034.
Report an issue: GitHub.