{"record":{"id":"71edf431c0cdd815","repo":"aio-libs/aiohttp","slug":"invalid-path-path-part","errorCode":null,"errorMessage":"Invalid path '{path}'['{part}']","messagePattern":"Invalid path '(.+?)'\\['(.+?)'\\]","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/web_urldispatcher.py","lineNumber":426,"sourceCode":"        super().__init__(name=name)\n        self._orig_path = path\n        pattern = \"\"\n        formatter = \"\"\n        for part in ROUTE_RE.split(path):\n            match = self.DYN.fullmatch(part)\n            if match:\n                pattern += \"(?P<{}>{})\".format(match.group(\"var\"), self.GOOD)\n                formatter += \"{\" + match.group(\"var\") + \"}\"\n                continue\n\n            match = self.DYN_WITH_RE.fullmatch(part)\n            if match:\n                pattern += \"(?P<{var}>{re})\".format(**match.groupdict())\n                formatter += \"{\" + match.group(\"var\") + \"}\"\n                continue\n\n            if \"{\" in part or \"}\" in part:\n                raise ValueError(f\"Invalid path '{path}'['{part}']\")\n\n            part = _requote_path(part)\n            formatter += part\n            pattern += re.escape(part)\n\n        try:\n            compiled = re.compile(pattern)\n        except re.error as exc:\n            raise ValueError(f\"Bad pattern '{pattern}': {exc}\") from None\n        assert compiled.pattern.startswith(PATH_SEP)\n        assert formatter.startswith(\"/\")\n        self._pattern = compiled\n        self._formatter = formatter\n\n    @property\n    def canonical(self) -> str:\n        return self._formatter\n","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/web_urldispatcher.py#L408-L444","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\napp.router.add_get('/users/{id', handler)   # unclosed brace\n// after\napp.router.add_get('/users/{id}', handler)  # closed","handlingStrategy":"validation","validationCode":"import re\n\ndef validate_path_template(path: str) -> None:\n    for segment in path.strip('/').split('/'):\n        # allow {var} or {var:re}; flag stray braces\n        stripped = re.sub(r'\\{[^{}]*(:[^{}]*)?\\}', '', segment)\n        if '{' in stripped or '}' in stripped:\n            raise ValueError(f'Invalid path segment: {segment!r}')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use braces only for variables; {name} or {name:regex}.","Validate path templates in a helper before registration.","Lint route definitions for unmatched braces."],"tags":["routing","path-template","validation"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}