{"record":{"id":"cd0cdd1c667bbcee","repo":"twigphp/Twig","slug":"regexp-s-passed-to-matches-is-not-valid","errorCode":null,"errorMessage":"Regexp \"%s\" passed to \"matches\" is not valid","messagePattern":"Regexp \"(.+?)\" passed to \"matches\" is not valid","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/Extension/CoreExtension.php","lineNumber":1196,"sourceCode":"                return $a <=> (string) $b;\n            }\n\n            return (float) $aTrim <=> $b;\n        }\n\n        // fallback to <=>\n        return $a <=> $b;\n    }\n\n    /**\n     * @throws RuntimeError When the regular expression cannot be evaluated\n     *\n     * @internal\n     */\n    public static function matches(string $regexp, ?string $str): int\n    {\n        set_error_handler(static function ($t, $m) use ($regexp) {\n            throw new RuntimeError(\\sprintf('Regexp \"%s\" passed to \"matches\" is not valid', $regexp).substr($m, 12));\n        });\n        try {\n            if (false === $result = preg_match($regexp, $str ?? '')) {\n                throw new RuntimeError(\\sprintf('Regexp \"%s\" passed to \"matches\" failed: %s.', $regexp, preg_last_error_msg()));\n            }\n\n            return $result;\n        } finally {\n            restore_error_handler();\n        }\n    }\n\n    /**\n     * Returns a trimmed string.\n     *\n     * @param string|\\Stringable|null $string\n     * @param string|null             $characterMask\n     * @param string                  $side          left, right, or both","sourceCodeStart":1178,"sourceCodeEnd":1214,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/Extension/CoreExtension.php#L1178-L1214","documentation":"The Twig `matches` operator/filter runs preg_match on the given PCRE pattern. When preg_match emits a warning (malformed pattern, bad modifiers, etc.), a custom error handler converts it into a RuntimeError quoting the invalid regexp plus PHP's own warning text (the leading 'preg_match(): ' prefix is stripped via substr($m, 12)).","triggerScenarios":"{{ email matches '/^[a-z]+$/i' }} with a malformed pattern such as unmatched delimiters ('abc'), unbalanced parentheses ('/(/'), unknown modifiers ('/x/u_z'), or patterns that fail compilation; a truncated pattern built by string interpolation.","commonSituations":"Building regexes dynamically from user/config input with unescaped delimiters; patterns authored for another flavor (e.g. JavaScript) using unsupported constructs; missing delimiters when copying regexes from other tools; multibyte modifier mistakes.","solutions":["Fix the pattern: wrap it in delimiters (e.g. '/pattern/') and verify it compiles (test with preg_match in PHP or an online PCRE checker).","Escape or choose delimiters that do not appear in the pattern, or use alternative delimiters like '#...#'.","If the pattern is dynamic, validate it before use (e.g. @preg_match($pattern, '') === false check) and fall back to a safe pattern.","Remove unsupported modifiers/constructs for PHP PCRE (compare with the regex source syntax)."],"exampleFix":"// before (template)\n{% if value matches '^[0-9]+$' %}\n\n// after\n{% if value matches '/^[0-9]+$/' %}","handlingStrategy":"try-catch","validationCode":"// Validate a PCRE pattern before using it in matches\nfunction isValidPcre(string $pattern): bool {\n    return @\\preg_match($pattern, '') !== false;\n}","typeGuard":null,"tryCatchPattern":"try {\n    $ok = \\Twig\\Extension\\CoreExtension::matches($regexp, $str);\n} catch (\\Twig\\Error\\RuntimeError $e) {\n    // invalid regexp: log and treat as non-match or use a fallback pattern\n    $ok = 0;\n}","preventionTips":["Always delimit patterns: '/pattern/', '#pattern#'.","Test dynamic patterns with @preg_match before rendering.","Escape delimiters inside patterns or pick delimiters not used in the expression.","Validate user-supplied regex input against a safe subset/length limit."],"tags":["twig","regex","pcre","matches"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}