{"id":"753dbb15c044aed5","repo":"aio-libs/aiohttp","slug":"method-is-not-allowed-http-method","errorCode":null,"errorMessage":"{method} is not allowed HTTP method","messagePattern":"(.+?) is not allowed HTTP method","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/web_urldispatcher.py","lineNumber":166,"sourceCode":"class AbstractRoute(abc.ABC):\n    def __init__(\n        self,\n        method: str,\n        handler: Handler | type[AbstractView],\n        *,\n        expect_handler: _ExpectHandler | None = None,\n        resource: AbstractResource | None = None,\n    ) -> None:\n        if expect_handler is None:\n            expect_handler = _default_expect_handler\n\n        assert inspect.iscoroutinefunction(expect_handler) or (\n            sys.version_info < (3, 14) and asyncio.iscoroutinefunction(expect_handler)  # type: ignore[deprecated]\n        ), f\"Coroutine is expected, got {expect_handler!r}\"\n\n        method = method.upper()\n        if not HTTP_METHOD_RE.match(method):\n            raise ValueError(f\"{method} is not allowed HTTP method\")\n\n        if inspect.iscoroutinefunction(handler) or (\n            sys.version_info < (3, 14) and asyncio.iscoroutinefunction(handler)  # type: ignore[deprecated]\n        ):\n            pass\n        elif isinstance(handler, type) and issubclass(handler, AbstractView):\n            pass\n        else:\n            raise TypeError(\n                f\"Only async functions are allowed as web-handlers, got {handler!r}\"\n            )\n\n        self._method = method\n        self._handler = handler\n        self._expect_handler = expect_handler\n        self._resource = resource\n\n    @property","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/web_urldispatcher.py#L148-L184","documentation":"Raised as ValueError by Route.__init__ (via add_route/add_get/add_post etc.) when the HTTP method string does not match HTTP_METHOD_RE (token chars defined by RFC 7230). The method is uppercased then matched against the allowed token grammar, so malformed methods, methods with spaces, or typos are rejected before route registration.","triggerScenarios":"Calling app.router.add_route('GETT', '/', handler), add_route('GET POST', ...), add_route('', ...), or passing a method with illegal characters. Also app.router.add_get with a typo like 'get ' (trailing space) after uppercasing yields 'GET ' which fails the regex.","commonSituations":"Typing the method name; passing a method read from config with whitespace/newline; concatenating methods; using lowercase is fine (uppercased internally) but embedded spaces or slashes are not; confusion with hdrs.METH_ANY which is handled separately for ANY routes.","solutions":["Use a single valid RFC 7230 method token: 'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'.","For matching any method use app.router.add_route('*', path, handler) which maps to METH_ANY.","Strip/validate methods read from external config: method.strip().upper() before passing.","Register separate routes for each method instead of comma/space-separated lists."],"exampleFix":"# before\napp.router.add_route('GET POST', '/items', handler)\n\n# after\napp.router.add_route('GET', '/items', handler)\napp.router.add_route('POST', '/items', handler)","handlingStrategy":"validation","validationCode":"import re\nfrom aiohttp.web_urldispatcher import HTTP_METHOD_RE\n\ndef normalize_method(method: str) -> str:\n    m = method.strip().upper()\n    if not HTTP_METHOD_RE.match(m):\n        raise ValueError(f\"Invalid HTTP method: {method!r}\")\n    return m","typeGuard":"from aiohttp.web_urldispatcher import HTTP_METHOD_RE\n\ndef is_valid_method(method: str) -> bool:\n    return isinstance(method, str) and bool(HTTP_METHOD_RE.match(method.strip().upper()))","tryCatchPattern":"try:\n    app.router.add_route(method, path, handler)\nexcept ValueError as e:\n    raise ValueError(f\"Rejected method {method!r}: {e}\") from e","preventionTips":["Centralize method normalization for config-driven routes.","Use the aiohttp hdrs constants (hdrs.METH_GET) for stock methods.","Lint route registrations in a test that exercises every add_route call."],"tags":["aiohttp","routing","http-method","value-error","registration"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}