rectorphp/rector · error · InvalidEregException

"-" is invalid for the start character in the brackets

Error message

"-" is invalid for the start character in the brackets

What it means

Inside processSquareBracket(), a '-' was consumed as a class member at a position where it is not the first character and is not immediately followed by ']' — i.e. it is neither a leading/trailing literal dash nor the start of a valid range, which POSIX ERE rejects (EregToPcreTransformer.php:216). The InvalidEregException with message '"-" is invalid for the start character in the brackets' aborts the conversion.

Source

Thrown at rules/Php70/EregToPcreTransformer.php:216

        }
        // retype
        $i = (int) $i;
        return $i;
    }
    /**
     * @return float[]|int[]|string[]
     */
    private function processSquareBracket(string $s, int $i, int $l, string $cls, bool $start): array
    {
        do {
            if ($s[$i] === '[' && $i + 1 < $l && strpos('.=:', $s[$i + 1]) !== \false) {
                /** @var string $cls */
                [$cls, $i] = $this->processCharacterClass($s, $i, $cls);
            } else {
                $a = $s[$i];
                ++$i;
                if ($a === '-' && !$start && ($i >= $l || $s[$i] !== ']')) {
                    throw new InvalidEregException('"-" is invalid for the start character in the brackets');
                }
                if ($i < $l && $s[$i] === '-') {
                    $b = $s[++$i];
                    if ($b === ']') {
                        $cls .= $this->_ere2pcre_escape($a) . '\-';
                        break;
                    }
                    if (ord($a) > ord($b)) {
                        $errorMessage = sprintf('an invalid character range %d-%d"', (int) $a, (int) $b);
                        throw new InvalidEregException($errorMessage);
                    }
                    $cls .= $this->_ere2pcre_escape($a) . '-' . $this->_ere2pcre_escape($b);
                    ++$i;
                } else {
                    $cls .= $this->_ere2pcre_escape($a);
                }
            }
            $start = \false;

View on GitHub (pinned to 408fcb0ff1)

Solutions

  1. Rewrite the class in the flagged file so '-' is a range start, range end, or escaped/edge literal: '[0-9-x]' -> '[0-9x]' or '[0-9\-x]'.
  2. If the dash is literal, move it to the end ('[0-9x-]') or escape it ('[0-9\-x]').
  3. Re-run rector; preflight literal ereg patterns for '-' not adjacent to '[' or ']' inside classes.

Example fix

// before - '-' at atom position inside class
ereg('[0-9-x]', $subject);

// after - dash handled explicitly
ereg('[0-9x-]', $subject); // rector: preg_match('#[0-9x-]#m', $subject)
Defensive patterns

Strategy: try-catch

Validate before calling

// quick lint: '-' mid-class not adjacent to '[' or ']'
function dashMisplacedInClass(string $p): bool {
    return (bool) preg_match('~(?<!^)(?<!\[)-(?![\]\\])~', $p);
}

Try / catch

try {
    $pcre = $eregToPcreTransformer->transform($pattern, $ignoreCase);
} catch (InvalidEregException $e) {
    // '-' used where a class member must start — move it to the class edge or escape it
    continue;
}

Prevention

When it happens

Trigger: Rector (Php70 set / EregToPregMatchRector, target PHP >= 7.0) visits an ereg-family call whose literal pattern has a '-' mid-class where a character should start, e.g. `ereg('[0-9-x]', $s)` (after the range 0-9, '-' is followed by 'x', not ']'), or `split('[abc-', $s)` style content where '-' precedes a non-']' character at class end. Note '[a-]' and '[-a]' are accepted; '[ab-9]' is not.

Common situations: Character classes edited by appending '-x' to an existing range ('[0-9]' -> '[0-9-x]') which silently changes '-' into an atom position; glob/habit thinking where '-' separates members; legacy patterns that relied on lenient behavior of other engines.

Related errors


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