{"record":{"id":"1749886957573857","repo":"rectorphp/rector","slug":"an-invalid-escape-sequence-at-the-end","errorCode":null,"errorMessage":"an invalid escape sequence at the end","messagePattern":"an invalid escape sequence at the end","errorType":"validation","errorClass":"InvalidEregException","httpStatus":null,"severity":"error","filePath":"rules/Php70/EregToPcreTransformer.php","lineNumber":148,"sourceCode":"                    throw new InvalidEregException('unescaped metacharacter \"' . $char . '\"');\n                }\n            } elseif ($char === '.') {\n                $r[$rr] .= $char;\n            } elseif ($char === '^' || $char === '$') {\n                $r[$rr] .= $char;\n                ++$i;\n                continue;\n            } elseif ($char === '|') {\n                if ($r[$rr] === '') {\n                    $normalizeUnprintableChar = \\true;\n                }\n                $r[] = '';\n                ++$rr;\n                ++$i;\n                continue;\n            } elseif ($char === '\\\\') {\n                if (++$i >= $l) {\n                    throw new InvalidEregException('an invalid escape sequence at the end');\n                }\n                $r[$rr] .= $this->_ere2pcre_escape($content[$i]);\n            } else {\n                // 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);","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/rectorphp/rector/blob/408fcb0ff1833e3d26cbc9b04c23a77565814a16/rules/Php70/EregToPcreTransformer.php#L130-L166","documentation":"The ERE pattern being converted to PCRE ends with a lone backslash (EregToPcreTransformer.php:148). A trailing '\\' opens an escape sequence but has nothing to escape, which is invalid in POSIX ERE, so EregToPcreTransformer throws InvalidEregException and the ereg-to-preg rewrite of that call aborts.","triggerScenarios":"Rector (Php70 set / EregToPregMatchRector, target PHP >= 7.0) visits an ereg-family call whose first argument is a string literal ending in a backslash. Note PHP string semantics: \"abc\\\\\" in source is the 4-char pattern abc\\ and triggers it; 'C:\\path\\' with a real trailing backslash also does. After the '\\' branch does ++$i >= $l, the exception 'an invalid escape sequence at the end' is thrown.","commonSituations":"Windows path or DOS-prefix patterns ('C:\\\\') where the final backslash was meant literally but never doubled; patterns chopped by an edit so the escaped character after '\\' was lost; PHP single-quoted strings where the author did not realize a trailing '\\' is a literal backslash that ERE cannot carry at the end.","solutions":["Fix the literal in the file Rector reported: double the trailing backslash so it becomes an escaped literal '\\\\\\\\' (ERE for one literal backslash), or drop it if it was accidental.","Re-run rector to confirm the ereg call now converts to preg_match cleanly.","In bulk migrations, grep ereg/split string literals for patterns ending with an odd number of backslashes first."],"exampleFix":"// before - pattern ends with lone backslash (PHP string 'C:\\\\path\\\\' => C:\\path\\)\nereg('C:\\\\path\\\\', $subject);\n\n// after - trailing backslash escaped\nereg('C:\\\\path\\\\\\\\\\\\\\\\', $subject);","handlingStrategy":"try-catch","validationCode":"// quick lint: pattern ends with an odd run of backslashes\nfunction endsInLoneBackslash(string $p): bool {\n    $n = 0; $i = strlen($p) - 1;\n    while ($i >= 0 && $p[$i] === '\\\\') { $n++; $i--; }\n    return $n % 2 === 1;\n}","typeGuard":null,"tryCatchPattern":"try {\n    $pcre = $eregToPcreTransformer->transform($pattern, $ignoreCase);\n} catch (InvalidEregException $e) {\n    // trailing escape with nothing to escape — double or drop the final backslash\n    continue;\n}","preventionTips":["In single-quoted PHP strings a trailing '\\\\' is a real backslash; double it when it must be a literal in ERE ('\\\\\\\\').","Be extra careful with Windows-path patterns; verify the literal ends with an even number of backslashes.","Run the transformer over collected literals once before the real rector pass."],"tags":["rector","php","regex","posix-ere","escaping","migration"],"backgroundTag":"invalid-regex-syntax","analyzedSha":"408fcb0ff1833e3d26cbc9b04c23a77565814a16","analyzedAt":"2026-08-21T05:11:02.643Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}