aio-libs/aiohttp · error · ValueError
is not allowed HTTP method
Error message
{method} is not allowed HTTP method What it means
When registering a route, aiohttp uppercases the method and validates it against HTTP_METHOD_RE (RFC 7230 token characters: alphanumerics and a subset of symbols). A method that does not match — e.g. contains spaces, lowercase handled fine by upper(), but embedded slashes, colons, or empty strings — raises ValueError. This protects the router from registering routes that can never match a real HTTP request line.
Solutions
- Pass a single, valid HTTP method token as a string: 'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', or a custom token matching [A-Za-z0-9!#$%&'*+-.^_`|~].
- If you have a comma-separated list, split and register each method individually.
- Strip whitespace and verify there are no newline/control characters before registering.
Example fix
// before
resource.add_route('GET, POST', handler)
// after
resource.add_route('GET', handler)
resource.add_route('POST', handler) Defensive patterns
Strategy: validation
Validate before calling
import re
from aiohttp.web_urldispatcher import HTTP_METHOD_RE
def validate_method(method: str) -> str:
method = method.upper()
if not HTTP_METHOD_RE.match(method):
raise ValueError(f'Invalid HTTP method: {method!r}')
return method Prevention
- Use the named helpers (add_get, add_post, add_put, add_delete, add_patch, add_head, add_options) instead of add_route for standard verbs.
- Never pass comma-separated method lists; register each verb separately.
- Unit-test route registration to catch malformed methods at test time.
When it happens
Trigger: Calling resource.add_route() or app.router.add_route() / app.router.add_get() with a malformed method string: empty string, a string containing spaces or commas (e.g. 'GET, POST'), a method with invalid characters like 'GET/' or 'GET\n'. Also passing a method already containing a custom verb with disallowed punctuation.
Common situations: Typos; splitting a comma-separated method list instead of registering each separately; passing the full HTTP request line ('GET /path'); using a method name with a hyphen that includes an invalid symbol; test code that passes arbitrary strings.
Related errors
- Bad pattern
- Domain cannot be empty
- Invalid path ' '[' ']
- Method cannot contain non-token characters
- Prefix cannot be empty
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/753dbb15c044aed5.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/web_urldispatcher.py:166
class AbstractRoute(abc.ABC):
def __init__(
self,
method: str,
handler: Handler | type[AbstractView],
*,
expect_handler: _ExpectHandler | None = None,
resource: AbstractResource | None = None,
) -> None:
if expect_handler is None:
expect_handler = _default_expect_handler
assert inspect.iscoroutinefunction(expect_handler) or (
sys.version_info < (3, 14) and asyncio.iscoroutinefunction(expect_handler) # type: ignore[deprecated]
), f"Coroutine is expected, got {expect_handler!r}"
method = method.upper()
if not HTTP_METHOD_RE.match(method):
raise ValueError(f"{method} is not allowed HTTP method")
if inspect.iscoroutinefunction(handler) or (
sys.version_info < (3, 14) and asyncio.iscoroutinefunction(handler) # type: ignore[deprecated]
):
pass
elif isinstance(handler, type) and issubclass(handler, AbstractView):
pass
else:
raise TypeError(
f"Only async functions are allowed as web-handlers, got {handler!r}"
)
self._method = method
self._handler = handler
self._expect_handler = expect_handler
self._resource = resource
@propertyView on GitHub (pinned to d041d4d0fd)