{"record":{"id":"9390fd1fc9d409bd","repo":"rectorphp/rector","slug":"empty-regular-expression-or-branch","errorCode":null,"errorMessage":"empty regular expression or branch","messagePattern":"empty regular expression or branch","errorType":"validation","errorClass":"InvalidEregException","httpStatus":null,"severity":"error","filePath":"rules/Php70/EregToPcreTransformer.php","lineNumber":170,"sourceCode":"                // including ] and } which are allowed as a literal character\n                $r[$rr] .= $this->_ere2pcre_escape($char);\n            }\n            ++$i;\n            if ($i >= $l) {\n                break;\n            }\n            // piece after the atom (only ONE of them is possible)\n            $char = $content[$i];\n            if (in_array($char, ['*', '+', '?'], \\true)) {\n                $r[$rr] .= $char;\n                ++$i;\n            } elseif ($char === '{') {\n                $i = (int) $i;\n                $i = $this->processCurlyBracket($content, $i, $r, $rr);\n            }\n        }\n        if ($r[$rr] === '') {\n            throw new InvalidEregException('empty regular expression or branch');\n        }\n        return [$this->normalize(implode('|', $r), $normalizeUnprintableChar), $i];\n    }\n    private function normalize(string $content, bool $normalizeUnprintableChar): string\n    {\n        if ($normalizeUnprintableChar) {\n            $content = str_replace(\"\\f\", '\\\\\\\\f', $content);\n        }\n        return str_replace($this->pcreDelimiter, '\\\\' . $this->pcreDelimiter, $content);\n    }\n    /**\n     * @param array<int, mixed> $r\n     */\n    private function processBracket(string $content, int $i, int $l, array &$r, int $rr): int\n    {\n        // special case\n        if ($i + 1 < $l && $content[$i + 1] === ')') {\n            $r[$rr] .= '()';","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/rectorphp/rector/blob/408fcb0ff1833e3d26cbc9b04c23a77565814a16/rules/Php70/EregToPcreTransformer.php#L152-L188","documentation":"After parsing the whole ERE pattern (or a branch), EregToPcreTransformer found the last branch empty — the pattern itself is '' or it ends with '|' leaving nothing after it (EregToPcreTransformer.php:170). POSIX ERE forbids empty patterns and empty alternation branches, so the conversion to PCRE is refused with InvalidEregException('empty regular expression or branch').","triggerScenarios":"Rector with the Php70 set / EregToPregMatchRector (target PHP >= 7.0) encounters an ereg-family call whose literal first argument is '' or ends with '|', e.g. `ereg('', $s)`, `split('a|', $s)`, or `ereg('|a', $s)` (the leading-empty branch only throws if the final branch is also empty, but trailing '|' always does). The final check `if ($r[$rr] === '')` fires before normalize() runs.","commonSituations":"Placeholder/empty-string patterns passed to split() to split on 'nothing'; dynamically built patterns whose optional chunk was empty; refactors that removed the last alternative but left the '|' separator.","solutions":["Give the pattern real content: replace '' with the intended expression, and remove the trailing '|' ('a|' -> 'a').","If the pattern is built dynamically, guard it so it cannot become empty before the ereg call.","Re-run rector; preflight-scan literal ereg/split patterns for '' and trailing '|'."],"exampleFix":"// before - trailing alternation with empty branch\nsplit('a|', $subject);\n\n// after - complete alternation\nsplit('a|b', $subject); // rector: preg_split('#a|b#m', $subject)","handlingStrategy":"validation","validationCode":"// guard dynamically built patterns before the legacy call\nif ($pattern === '' || substr($pattern, -1) === '|') {\n    throw new InvalidArgumentException('ereg pattern must be non-empty and must not end with |');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $pcre = $eregToPcreTransformer->transform($pattern, $ignoreCase);\n} catch (InvalidEregException $e) {\n    // pattern or final alternation branch is empty — give it content\n    continue;\n}","preventionTips":["Never pass '' or a trailing '|' to ereg/split; add a guard where patterns are assembled.","When removing an alternative from 'a|b|c', also remove the adjacent '|'.","Lint literals for empty strings and trailing pipes before the migration."],"tags":["rector","php","regex","posix-ere","alternation","migration"],"backgroundTag":"invalid-regex-syntax","analyzedSha":"408fcb0ff1833e3d26cbc9b04c23a77565814a16","analyzedAt":"2026-08-21T05:11:02.643Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}