aio-libs/aiohttp · error · ValueError
Invalid path ' '[' ']
Error message
Invalid path '{path}'['{part}'] What it means
While parsing a path template (e.g. '/users/{id}'), the PatternBuilder splits on '/' and processes each segment. If a segment contains a '{' or '}' that does not match the dynamic-variable syntax (DYN or DYN_WITH_RE forms like '{name}' or '{name:regex}'), the parser cannot interpret it and raises ValueError. This catches malformed path templates before they compile into a regex that would match unexpected things.
Solutions
- Use braces only to declare path variables: '/users/{id}' or '/users/{id:\d+}'.
- Remove any literal '{' or '}' that is not part of a variable declaration.
- If you need a literal brace in the URL, avoid the template engine (register a catch-all and parse manually) or restructure the path.
Example fix
// before
app.router.add_get('/users/{id', handler) # unclosed brace
// after
app.router.add_get('/users/{id}', handler) # closed Defensive patterns
Strategy: validation
Validate before calling
import re
def validate_path_template(path: str) -> None:
for segment in path.strip('/').split('/'):
# allow {var} or {var:re}; flag stray braces
stripped = re.sub(r'\{[^{}]*(:[^{}]*)?\}', '', segment)
if '{' in stripped or '}' in stripped:
raise ValueError(f'Invalid path segment: {segment!r}') Prevention
- Use braces only for variables; {name} or {name:regex}.
- Validate path templates in a helper before registration.
- Lint route definitions for unmatched braces.
When it happens
Trigger: Calling app.router.add_route with a path containing unmatched or misplaced braces: '/users/{', '/users/}', '/users/{id{', '/users/}id', '/users/foo}bar', or a segment like '/a{b' where a brace is not part of a valid {var} or {var:re} group.
Common situations: Typos in path templates; attempting to use literal braces in a path without escaping (braces are reserved for variables); partial copy-paste of a dynamic route; path templates built by string concatenation that accidentally leaves stray braces.
Related errors
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/71edf431c0cdd815.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/web_urldispatcher.py:426
super().__init__(name=name)
self._orig_path = path
pattern = ""
formatter = ""
for part in ROUTE_RE.split(path):
match = self.DYN.fullmatch(part)
if match:
pattern += "(?P<{}>{})".format(match.group("var"), self.GOOD)
formatter += "{" + match.group("var") + "}"
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
View on GitHub (pinned to d041d4d0fd)