pydantic/pydantic · error · PydanticCustomError

pattern_regex

pattern_regex

Error message

Input should be a valid regular expression

What it means

Raised by compile_pattern (pydantic/_internal/_validators.py:175, code 'pattern_regex') when re.compile() fails on the supplied pattern string/bytes. The re.error is caught and surfaced as a pydantic validation error, indicating the input is syntactically not a valid regular expression.

Source

Thrown at pydantic/_internal/_validators.py:175

            return input_value
        else:
            raise PydanticCustomError('pattern_bytes_type', 'Input should be a bytes pattern')
    elif isinstance(input_value, bytes):
        return compile_pattern(input_value)
    elif isinstance(input_value, str):
        raise PydanticCustomError('pattern_bytes_type', 'Input should be a bytes pattern')
    else:
        raise PydanticCustomError('pattern_type', 'Input should be a valid pattern')


PatternType = TypeVar('PatternType', str, bytes)


def compile_pattern(pattern: PatternType) -> re.Pattern[PatternType]:
    try:
        return re.compile(pattern)
    except re.error:
        raise PydanticCustomError('pattern_regex', 'Input should be a valid regular expression')


def ip_v4_address_validator(input_value: Any, /) -> IPv4Address:
    if isinstance(input_value, IPv4Address):
        return input_value

    try:
        return IPv4Address(input_value)
    except ValueError:
        raise PydanticCustomError('ip_v4_address', 'Input is not a valid IPv4 address')


def ip_v6_address_validator(input_value: Any, /) -> IPv6Address:
    if isinstance(input_value, IPv6Address):
        return input_value

    try:
        return IPv6Address(input_value)

View on GitHub (pinned to 2e5f0e2b42)

Solutions

  1. Test the regex in isolation: `python -c "import re; re.compile('YOUR_PATTERN')"` to reproduce the re.error.
  2. Fix the specific syntax error (close brackets/parens, remove invalid quantifiers, escape literals).
  3. When interpolating untrusted/dynamic substrings, wrap them with `re.escape()`.
  4. If the value is meant to be a literal match, use plain str equality/`in` instead of a regex.

Example fix

# before
class M(BaseModel):
    p: Pattern
M(p='[a-')  # unclosed character class -> pattern_regex

# after
M(p='[a-z-]')  # valid character class
Defensive patterns

Strategy: validation

Validate before calling

import re
from typing import Any

def try_compile(pattern: Any) -> bool:
    try:
        re.compile(pattern)
        return True
    except (re.error, TypeError):
        return False

Type guard

import re
from typing import Any

def is_compilable_pattern(value: Any) -> bool:
    try:
        re.compile(value)
        return True
    except (re.error, TypeError, ValueError):
        return False

Try / catch

import re
try:
    re.compile(user_pattern)
except re.error as e:
    # reject the input with a clear 4xx-style message before model validation
    raise ValueError(f'invalid regex: {e}') from e

Prevention

When it happens

Trigger: Any Pattern field (Pattern, Pattern[str], or Pattern[bytes]) validated with a string/bytes containing malformed regex syntax — unclosed brackets `[a-`, unbalanced parentheses `(foo`, invalid quantifiers `*+`, invalid escape sequences in strict mode, or stray meta-characters.

Common situations: User-supplied search patterns (search boxes, filter inputs). Regex sourced from config files authored without testing. Escaping mistakes when interpolating dynamic values into a regex (forgetting re.escape). Copy-paste from documentation that mangled special characters. Python regex flavor differences vs PCRE/JS.

Related errors


AI-assisted analysis of pydantic/pydantic@2e5f0e2b42 (2026-08-04). Data as JSON: /data/errors/8775f2376d15d1d6.json. Report an issue: GitHub.