twigphp/Twig · error · RuntimeError

Regexp " " passed to "matches" is not valid

Error message

Regexp "%s" passed to "matches" is not valid

What it means

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)).

Solutions

  1. 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).
  2. Escape or choose delimiters that do not appear in the pattern, or use alternative delimiters like '#...#'.
  3. If the pattern is dynamic, validate it before use (e.g. @preg_match($pattern, '') === false check) and fall back to a safe pattern.
  4. Remove unsupported modifiers/constructs for PHP PCRE (compare with the regex source syntax).

Example fix

// before (template)
{% if value matches '^[0-9]+$' %}

// after
{% if value matches '/^[0-9]+$/' %}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate a PCRE pattern before using it in matches
function isValidPcre(string $pattern): bool {
    return @\preg_match($pattern, '') !== false;
}

Try / catch

try {
    $ok = \Twig\Extension\CoreExtension::matches($regexp, $str);
} catch (\Twig\Error\RuntimeError $e) {
    // invalid regexp: log and treat as non-match or use a fallback pattern
    $ok = 0;
}

Prevention

When it happens

Trigger: {{ 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.

Common situations: 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.

Related errors


AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13). Data as JSON: /api/errors/cd0cdd1c667bbcee. Report an issue: GitHub.

Appendix: source

Thrown at src/Extension/CoreExtension.php:1196

                return $a <=> (string) $b;
            }

            return (float) $aTrim <=> $b;
        }

        // fallback to <=>
        return $a <=> $b;
    }

    /**
     * @throws RuntimeError When the regular expression cannot be evaluated
     *
     * @internal
     */
    public static function matches(string $regexp, ?string $str): int
    {
        set_error_handler(static function ($t, $m) use ($regexp) {
            throw new RuntimeError(\sprintf('Regexp "%s" passed to "matches" is not valid', $regexp).substr($m, 12));
        });
        try {
            if (false === $result = preg_match($regexp, $str ?? '')) {
                throw new RuntimeError(\sprintf('Regexp "%s" passed to "matches" failed: %s.', $regexp, preg_last_error_msg()));
            }

            return $result;
        } finally {
            restore_error_handler();
        }
    }

    /**
     * Returns a trimmed string.
     *
     * @param string|\Stringable|null $string
     * @param string|null             $characterMask
     * @param string                  $side          left, right, or both

View on GitHub (pinned to a414c3a491)