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
- Test the regex in isolation: `python -c "import re; re.compile('YOUR_PATTERN')"` to reproduce the re.error.
- Fix the specific syntax error (close brackets/parens, remove invalid quantifiers, escape literals).
- When interpolating untrusted/dynamic substrings, wrap them with `re.escape()`.
- 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
- Test regexes with `re.compile()` in isolation before wiring them into config.
- Use `re.escape()` when interpolating untrusted substrings into a pattern.
- Prefer plain string matching (`in`, equality) when regex features are not needed.
- Add a config-load unit test that compiles every configured pattern.
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.