phacility/phabricator · error · Exception

Rule '%s' is not a valid regular expression.

Error message

Rule '%s' is not a valid regular expression.

What it means

While distributing files to atomizers, Diviner runs each `rules` key from the book configuration through preg_match(). PHP's preg_match returns false for a malformed pattern, and this Exception is thrown for the first rule that fails. In practice it almost always means the `.book` JSON has a rule key that is not a valid PCRE pattern — most commonly missing the delimiter characters (`/.../`) that PHP requires.

Source

Thrown at src/applications/diviner/workflow/DivinerGenerateWorkflow.php:275

    $this->log(pht('Done.')."\n");
  }

  private function getAtomizersForFiles(array $files) {
    $rules = $this->getRules();
    $exclude = $this->getExclude();
    $atomizers = array();

    foreach ($files as $file) {
      foreach ($exclude as $pattern) {
        if (preg_match($pattern, $file)) {
          continue 2;
        }
      }

      foreach ($rules as $rule => $atomizer) {
        $ok = preg_match($rule, $file);
        if ($ok === false) {
          throw new Exception(
            pht("Rule '%s' is not a valid regular expression.", $rule));
        }
        if ($ok) {
          $atomizers[$file] = $atomizer;
          continue;
        }
      }
    }

    return $atomizers;
  }

  private function getRules() {
    return $this->getConfig('rules', array(
      '/\\.diviner$/' => 'DivinerArticleAtomizer',
      '/\\.php$/' => 'DivinerPHPAtomizer',
    ));
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Wrap every rule key in delimiters: `"\\.php$"` becomes `"/\\.php$/"`
  2. Test each pattern in isolation: `php -r 'var_dump(preg_match("/PATTERN/", ""));'` should not print false
  3. Run a JSON lint on the `.book` file after editing to catch escaping damage

Example fix

// before (docs/book.book)
"rules": {"src/.*\\.php$": "DivinerPHPAtomizer"}
// after (PCRE delimiters added)
"rules": {"/src/.*\\.php$/": "DivinerPHPAtomizer"}
Defensive patterns

Strategy: validation

Validate before calling

$rules = idx($book, 'rules', array());
foreach (array_keys($rules) as $rule) {
  if (@preg_match($rule, '') === false) {
    // Reject the config before Diviner runs: the pattern is not valid PCRE.
    throw new Exception('Invalid regex in book config: '.$rule);
  }
}

Prevention

When it happens

Trigger: A `.book` file containing e.g. `"rules": {"\.php$": "DivinerPHPAtomizer"}` — the key lacks delimiters, so preg_match returns false. Also unbalanced parentheses/brackets, unknown modifiers after the closing delimiter, or a stray backslash.

Common situations: Authors writing regexes JSON-style (without delimiters) as in JS or Python; regexes that worked in another tool but were pasted into the `.book` file losing their delimiters; escaping mistakes through the double layer of JSON + PCRE (e.g. `\\.` needed for a literal dot).

Related errors


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