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

  1. Wrap the pattern in matching delimiter characters, e.g. change foo.*bar to @foo.*bar@ (or /foo.*/bar/ with the inner slash escaped).
  2. If the pattern contains the delimiter, either escape it (\/) or pick a different delimiter (@, #, ~, %).
  3. 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).
  4. 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

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


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