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
- 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.
- Re-run rector on the file to verify the ereg-to-preg conversion completes.
- 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
- Treat '[' without a following ']' in any literal regex as a build-breaking typo; fix before the migration run.
- When truncating or concatenating patterns, assert the result still ends outside a character class.
- Pre-check literal patterns with the transformer in a scratch script before running rector over the whole repo.
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
- "-" is invalid for the start character in the brackets
- an invalid character range %d-%d"
- an invalid or unsupported character class [%s]
- unescaped metacharacter ")"
- unescaped metacharacter "%s"
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/eba0d9d2177c5103.
Report an issue: GitHub.