rectorphp/rector · error · InvalidEregException

"[" does not have a matching "]"

Error message

"[" does not have a matching "]"

What it means

While converting an ERE pattern to PCRE, EregToPcreTransformer encountered a '[' (optionally followed by '^') at the very end of the pattern, so the character class has no chance of being closed. POSIX ERE requires every '[' to be matched by ']', so the pattern is invalid and InvalidEregException is thrown, aborting the EregToPregMatchRector conversion.

Source

Thrown at rules/Php70/EregToPcreTransformer.php:113

        $r = [''];
        $rr = 0;
        $l = strlen($content);
        $normalizeUnprintableChar = \false;
        while ($i < $l) {
            // atom
            $char = $content[$i];
            if ($char === '(') {
                $i = (int) $i;
                $i = $this->processBracket($content, $i, $l, $r, $rr);
            } elseif ($char === '[') {
                ++$i;
                $cls = '';
                if ($i < $l && $content[$i] === '^') {
                    $cls .= '^';
                    ++$i;
                }
                if ($i >= $l) {
                    throw new InvalidEregException('"[" does not have a matching "]"');
                }
                $start = \true;
                $i = (int) $i;
                [$cls, $i] = $this->processSquareBracket($content, $i, $l, $cls, $start);
                if ($i >= $l) {
                    throw new InvalidEregException('"[" does not have a matching "]"');
                }
                $r[$rr] .= '[' . $cls . ']';
            } elseif ($char === ')') {
                break;
            } elseif (in_array($char, ['*', '+', '?'], \true)) {
                throw new InvalidEregException('unescaped metacharacter "' . $char . '"');
            } elseif ($char === '{') {
                if ($i + 1 < $l && strpos('0123456789', $content[$i + 1]) !== \false) {
                    $r[$rr] .= '\{';
                } else {
                    throw new InvalidEregException('unescaped metacharacter "' . $char . '"');
                }

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Open the file Rector reported and complete the character class: turn 'abc[' into 'abc[x]' for the intended character set, or escape it as 'abc\[' if '[' is meant literally.
  2. Re-run rector on the file to verify the ereg-to-preg conversion completes.
  3. Preflight large migrations by scanning for string-literal ereg patterns that end in '[' or '[^' and fixing them first.

Example fix

// before - unterminated character class
ereg('abc[', $subject);

// after - closed class (or escape the bracket if literal)
ereg('abc[a-z]', $subject); // rector: preg_match('#abc[a-z]#m', $subject)
Defensive patterns

Strategy: try-catch

Validate before calling

$ok = true;
foreach (['abc[', 'x[^'] as $candidate) {
    try { (new EregToPcreTransformer())->transform($candidate, false); }
    catch (InvalidEregException $e) { $ok = false; echo "Unterminated class: {$candidate}\n"; }
}

Try / catch

try {
    $pcre = $eregToPcreTransformer->transform($pattern, $ignoreCase);
} catch (InvalidEregException $e) {
    // pattern ends right after '[' or '[^' — close the class in the source and re-run
    continue;
}

Prevention

When it happens

Trigger: Rector (Php70 set / EregToPregMatchRector, target PHP >= 7.0) visits an ereg-family call whose first argument is a string literal ending in '[' or '[^', e.g. `ereg('abc[', $s)` or `split('[^', $s)`. The check at EregToPcreTransformer.php:113 fires because the index after consuming '[' (and optional '^') already reached the end of the string.

Common situations: Legacy PHP 5 era code with typo'd character classes; a pattern truncated by a bad edit or a mis-quoted heredoc; concatenated pattern fragments where the closing ']' lived in a variable that is now a literal.

Related errors


AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21). Data as JSON: /api/errors/eba0d9d2177c5103. Report an issue: GitHub.