phacility/phabricator · error · HeraldInvalidConditionException
The regular expression "%s" is not valid. Regular expression
Error message
The regular expression "%s" is not valid. Regular expressions must have enclosing characters (e.g. "@/path/to/file@", not "/path/to/file") and be syntactically correct.
What it means
Thrown by HeraldAdapter::willSaveCondition() when a Herald rule with a 'matches regular expression' (CONDITION_REGEXP) or 'does not match regular expression' (CONDITION_NOT_REGEXP) condition is saved and PHP's preg_match() rejects the pattern. PCRE patterns in PHP must be wrapped in delimiter characters (e.g. '@' or '/'), so Phabricator deliberately runs a smoke-test match on the empty string and treats a boolean false return as an invalid pattern. The message shows the offending value and reminds you that delimiters are required (e.g. '@/path/to/file@').
Source
Thrown at src/applications/herald/adapter/HeraldAdapter.php:622
return (($condition_value & $field_value) === (int)$condition_value);
case self::CONDITION_NOT_BIT:
return (($condition_value & $field_value) !== (int)$condition_value);
default:
throw new HeraldInvalidConditionException(
pht("Unknown condition '%s'.", $condition_type));
}
}
public function willSaveCondition(HeraldCondition $condition) {
$condition_type = $condition->getFieldCondition();
$condition_value = $condition->getValue();
switch ($condition_type) {
case self::CONDITION_REGEXP:
case self::CONDITION_NOT_REGEXP:
$ok = @preg_match($condition_value, '');
if ($ok === false) {
throw new HeraldInvalidConditionException(
pht(
'The regular expression "%s" is not valid. Regular expressions '.
'must have enclosing characters (e.g. "@/path/to/file@", not '.
'"/path/to/file") and be syntactically correct.',
$condition_value));
}
break;
case self::CONDITION_REGEXP_PAIR:
$json = null;
try {
$json = phutil_json_decode($condition_value);
} catch (PhutilJSONParserException $ex) {
throw new HeraldInvalidConditionException(
pht(
'The regular expression pair "%s" is not valid JSON. Enter a '.
'valid JSON array with two elements.',
$condition_value));
}View on GitHub (pinned to 5720a38cfe)
Solutions
- Wrap the pattern in matching delimiter characters, e.g. change foo.*bar to @foo.*bar@ (or /foo.*/bar/ with the inner slash escaped).
- If the pattern contains the delimiter, either escape it (\/) or pick a different delimiter (@, #, ~, %).
- Sanity-check the pattern locally before saving: run php -r 'var_dump(@preg_match($argv[1], ""));' -- '@your@pattern@' — it must return int(0) or int(1), not bool(false).
- Check the trailing modifiers (i, m, s, u, x) are valid PCRE modifiers and spelled correctly.
Example fix
// before (condition value saved in Herald UI) foo/src/.*\.php // after — delimiters added, inner delimiter escaped @foo/src/.*\.php@
Defensive patterns
Strategy: validation
Validate before calling
// Validate before saving the rule / condition
$value = $condition->getValue();
if (@preg_match($value, '') === false) {
// reject with a form error; do NOT call HeraldEditor->save()
return pht('Invalid regexp: add delimiters, e.g. @pattern@');
} Type guard
function isValidHeraldRegexp($pattern) {
return is_string($pattern) && @preg_match($pattern, '') !== false;
} Try / catch
// If you call code that saves rules and cannot pre-validate:
try {
$editor->save();
} catch (HeraldInvalidConditionException $ex) {
// surface $ex->getMessage() as a field-level validation error,
// re-prompting the user with their input preserved
} Prevention
- Standardize on '@' delimiters for every Herald regex so '/' in paths never needs escaping.
- Lint regex conditions in a pre-save hook with @preg_match($value, '') before the HeraldEditor runs.
- When importing rules from other tools, run patterns through a converter that adds delimiters and escapes.
When it happens
Trigger: Saving any Herald rule whose condition value is a regex without enclosing delimiters (e.g. 'foo.*bar' instead of '@foo.*bar@'), with unbalanced or mismatched delimiters, with an unknown PCRE modifier (e.g. '@foo@z'), or with a syntax error inside the pattern. Triggered from the rule edit UI ('rule' JSON blob POST to /herald/edit/) or from any code path that calls HeraldEditor/HeraldRule save with a CONDITION_REGEXP condition.
Common situations: Users copy a regex from grep, JavaScript, or Python where delimiters are not used, and paste it directly into the Herald condition box. Typos in modifiers ('@pattern@i' mistyped as '@pattern@1'), forgetting the closing delimiter, or copy-pasting a pattern that contains the delimiter character unescaped are the usual causes.
Related errors
- The first regexp in the regexp pair, "%s", is not a valid re
- The second regexp in the regexp pair, "%s", is not a valid r
- The regular expression pair "%s" is not valid JSON. Enter a
- The regular expression pair "%s" must have exactly two eleme
- Unknown condition "%s"!
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/c30039d1c2c925d0.
Report an issue: GitHub.