rectorphp/rector · error · InvalidEregException
an invalid bound
Error message
an invalid bound
What it means
processCurlyBracket() extracted the text between '{' and '}' and validated it against BOUND_REGEX, which accepts only a minimum of 0-255 optionally followed by a comma and a maximum of 0-255 (or empty after the comma). Anything else — letters, spaces, numbers above 255, malformed commas — fails the match and InvalidEregException('an invalid bound') is thrown (EregToPcreTransformer.php:262), stopping the ereg-to-preg conversion.
Source
Thrown at rules/Php70/EregToPcreTransformer.php:262
return '\\' . $content;
}
return $content;
}
/**
* @param array<int, mixed> $r
*/
private function processCurlyBracket(string $s, int $i, array &$r, int $rr): int
{
$ii = strpos($s, '}', $i);
if ($ii === \false) {
throw new InvalidEregException('"{" does not have a matching "}"');
}
$start = $i + 1;
$length = $ii - ($i + 1);
$bound = Strings::substring($s, $start, $length);
$matches = Strings::match($bound, self::BOUND_REGEX);
if ($matches === null) {
throw new InvalidEregException('an invalid bound');
}
if (isset($matches[self::MAXIMAL_NUMBER_PART])) {
if ($matches[self::MINIMAL_NUMBER_PART] > $matches[self::MAXIMAL_NUMBER_PART]) {
throw new InvalidEregException('an invalid bound');
}
$r[$rr] .= '{' . $matches[self::MINIMAL_NUMBER_PART] . ',' . $matches[self::MAXIMAL_NUMBER_PART] . '}';
} elseif (isset($matches['comma'])) {
$r[$rr] .= '{' . $matches[self::MINIMAL_NUMBER_PART] . ',}';
} else {
$r[$rr] .= '{' . $matches[self::MINIMAL_NUMBER_PART] . '}';
}
return $ii + 1;
}
/**
* @return int[]|string[]
*/
private function processCharacterClass(string $content, int $i, string $cls): array
{View on GitHub (pinned to 408fcb0ff1)
Solutions
- Rewrite the bound to the accepted form in the flagged file: 'a{x}' -> 'a{2}', 'a{300}' -> repeat the atom or use '*'/'+' plus custom logic, 'a{2,3,4}' -> 'a{2,3}'.
- If the braces are literal text, escape them: 'a\{x\}'.
- Re-run rector; preflight literal ereg patterns for '{...}' content that is not a 1-3 digit number, optionally followed by a comma and 0-3 digits, with values <= 255.
Example fix
// before - bound content not 0-255[/0-255]
ereg('a{300}', $subject);
// after - valid bound
ereg('a{2}', $subject); // rector: preg_match('#a{2}#m', $subject) Defensive patterns
Strategy: validation
Validate before calling
// quick lint: bound body must be 1-3 digits, optional comma and 0-3 digits, values <= 255
function boundValid(string $body): bool {
if (!preg_match('~^([0-9]{1,3})(,([0-9]{0,3}))?$~', $body, $m)) return false;
if ((int) $m[1] > 255) return false;
return !isset($m[3]) || $m[3] === '' || (int) $m[3] <= 255;
} Try / catch
try {
$pcre = $eregToPcreTransformer->transform($pattern, $ignoreCase);
} catch (InvalidEregException $e) {
// bound body not '0-255[,0-255]' — rewrite it or escape literal braces
continue;
} Prevention
- Keep {min,max} counts within 0-255; restructure the pattern for larger repetitions.
- Escape braces used as placeholders ('\{name\}') so they are not parsed as bounds.
- Avoid spaces or extra commas inside bounds; ERE accepts none.
When it happens
Trigger: Rector (Php70 set / EregToPregMatchRector, target PHP >= 7.0) encounters an ereg-family call whose literal pattern has a syntactically complete but semantically invalid bound: `ereg('a{x}', $s)`, `split('a{2,3,4}', $s)`, `ereg('a{ 2}', $s)`, or out-of-range counts like `ereg('a{300}', $s)` / `ereg('a{1,999}', $s)` — BOUND_REGEX caps both parts at 25[0-5].
Common situations: Placeholder braces misread as quantifiers ('{name}', '{0}'); counts written for other regex dialects that allow larger or negative bounds; patterns edited so stray characters landed between the braces.
Related errors
- "{" does not have a matching "}"
- unescaped metacharacter "%s"
- unescaped metacharacter ")"
- "[" does not have a matching "]"
- an invalid escape sequence at the end
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/510685ab892971e7.
Report an issue: GitHub.