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

  1. 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}'.
  2. If the braces are literal text, escape them: 'a\{x\}'.
  3. 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

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


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