aio-libs/aiohttp · error · ValueError
Bad pattern '{pattern}': {exc}
Error message
Bad pattern '{pattern}': {exc} What it means
Raised as ValueError by DynamicResource.__init__ when the compiled regex built from the path template fails to compile (re.error). After converting the template into a regex pattern, aiohttp runs re.compile; if the user-supplied regex inside {var:regex} is invalid, the underlying re.error is wrapped and re-raised with this message.
Source
Thrown at aiohttp/web_urldispatcher.py:435
continue
match = self.DYN_WITH_RE.fullmatch(part)
if match:
pattern += "(?P<{var}>{re})".format(**match.groupdict())
formatter += "{" + match.group("var") + "}"
continue
if "{" in part or "}" in part:
raise ValueError(f"Invalid path '{path}'['{part}']")
part = _requote_path(part)
formatter += part
pattern += re.escape(part)
try:
compiled = re.compile(pattern)
except re.error as exc:
raise ValueError(f"Bad pattern '{pattern}': {exc}") from None
assert compiled.pattern.startswith(PATH_SEP)
assert formatter.startswith("/")
self._pattern = compiled
self._formatter = formatter
@property
def canonical(self) -> str:
return self._formatter
def add_prefix(self, prefix: str) -> None:
assert prefix.startswith("/")
assert not prefix.endswith("/")
assert len(prefix) > 1
self._pattern = re.compile(re.escape(prefix) + self._pattern.pattern)
self._formatter = prefix + self._formatter
def _match(self, path: str) -> dict[str, str] | None:
match = self._pattern.fullmatch(path)View on GitHub (pinned to c0ef574e29)
Solutions
- Test the regex in a Python shell with re.compile first, then paste it into the template.
- Use valid regex: '/items/{id:[0-9]+}' for digits, '/items/{slug:[a-z-]+}' for slugs.
- Remember the constraint is a full Python regex, not a glob — '*' alone is invalid.
- Escape literals like '.' as '\.' inside the constraint.
Example fix
# before
app.router.add_get('/items/{id:[0-9}', handler)
# after
app.router.add_get('/items/{id:[0-9]+}', handler) Defensive patterns
Strategy: validation
Validate before calling
import re
def validate_regex_constraint(pattern: str) -> str:
try:
re.compile(pattern)
except re.error as e:
raise ValueError(f"Invalid regex in path constraint {pattern!r}: {e}") from None
return pattern Type guard
import re
def is_compilable_regex(pattern: str) -> bool:
try:
re.compile(pattern)
return True
except re.error:
return False Try / catch
try:
app.router.add_get(path, handler)
except ValueError as e:
raise ValueError(f"Route regex failed to compile: {e}") from e Prevention
- Test regex constraints with re.compile in a REPL before embedding them.
- Remember the constraint is Python regex, not glob.
- Add a startup test that registers all routes to catch bad regex early.
When it happens
Trigger: Using an invalid regex in a variable constraint: app.router.add_get('/items/{id:[0-9', handler) (unclosed char class), '{id:(foo}' (unbalanced group), '{id:*}' (* is not a valid regex standalone), or any PCRE syntax Python's re rejects.
Common situations: Hand-writing regex constraints without testing; copy-paste truncating the regex; assuming glob syntax ('*' matches all) instead of regex; nested unescaped special chars.
Related errors
- Invalid path '{path}'['{part}']
- {method} is not allowed HTTP method
- Only async functions are allowed as web-handlers, got {handl
- Cannot change apps stack after .freeze() call
- Expected one of the following apps {self._apps!r}, got {app!
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/7d1982d97ba51800.json.
Report an issue: GitHub.