aio-libs/aiohttp · error · RuntimeError
Using chunked encoding is forbidden for HTTP/{request.versio
Error message
Using chunked encoding is forbidden for HTTP/{request.version.major}.{request.version.minor} What it means
Raised during response preparation when chunked transfer-encoding is enabled (`_chunked = True`) but the request was made over HTTP/1.0 (or any version other than 1.1). Chunked encoding is defined only in HTTP/1.1 (RFC 9112); emitting it on a 1.0 connection would corrupt the response. aiohttp refuses rather than sending malformed data.
Source
Thrown at aiohttp/web_response.py:393
writer = self._payload_writer
assert writer is not None
keep_alive = self._keep_alive
if keep_alive is None:
keep_alive = request.keep_alive
self._keep_alive = keep_alive
version = request.version
headers = self._headers
if self._cookies:
populate_with_cookies(headers, self._cookies)
if self._compression:
await self._start_compression(request)
if self._chunked:
if version != HttpVersion11:
raise RuntimeError(
"Using chunked encoding is forbidden "
f"for HTTP/{request.version.major}.{request.version.minor}"
)
if not self._must_be_empty_body:
writer.enable_chunking()
headers[hdrs.TRANSFER_ENCODING] = "chunked"
elif self._length_check: # Disabled for WebSockets
writer.length = self.content_length
if writer.length is None:
if version >= HttpVersion11:
if not self._must_be_empty_body:
writer.enable_chunking()
headers[hdrs.TRANSFER_ENCODING] = "chunked"
elif not self._must_be_empty_body:
keep_alive = False
# HTTP 1.1: https://tools.ietf.org/html/rfc7230#section-3.3.2
# HTTP 1.0: https://tools.ietf.org/html/rfc1945#section-10.4View on GitHub (pinned to d041d4d0fd)
Solutions
- Return a response with an explicit Content-Length so chunking is not needed (buffer the body fully).
- Ensure upstream clients/proxies speak HTTP/1.1; configure your reverse proxy to forward 1.1.
- Close the connection instead of streaming: set `resp.content_length` indirectly by using a fully-buffered body so no chunking is required.
- If you control the client, stop passing `-0` / `--http1.0` to curl or upgrade the client library.
Example fix
// before (streaming, no content-length, HTTP/1.0 client) resp = StreamResponse(status=200) resp.content_length = None await resp.prepare(request) await resp.write(chunk) # forces chunked -> RuntimeError on 1.0 // after body = b''.join(chunks) return Response(body=body, status=200) # Content-Length set automatically
Defensive patterns
Strategy: validation
Validate before calling
def stream_or_buffer(request, body_chunks):
if request.version != HttpVersion11:
# HTTP/1.0 cannot chunk — buffer fully
return Response(body=b''.join(body_chunks))
resp = StreamResponse()
resp.content_length = None
return resp Type guard
from aiohttp.http import HttpVersion11
def supports_chunked(request) -> bool:
return request.version == HttpVersion11 Prevention
- For 1.0 clients, buffer the body fully so Content-Length is set.
- Ensure upstream proxies forward HTTP/1.1.
- Avoid forcing Transfer-Encoding: chunked manually.
- Test streaming endpoints with curl --http1.1, not --http1.0.
When it happens
Trigger: Client connects via HTTP/1.0 (e.g. `curl -0`, some legacy proxies, or Python's httplib in HTTP/1.0 mode) and the handler returns a streaming Response with no Content-Length, forcing chunked encoding. Also reproducible by enabling `enable_chunking()` on a writer for a 1.0 request, or forcing `Transfer-Encoding: chunked` on a response served to a 1.0 client.
Common situations: A proxy/load-balancer downgrades the protocol to HTTP/1.0; curl with `--http1.0` for testing; an embedded/legacy HTTP client speaking 1.0; misconfigured reverse proxy stripping Content-Length and forcing chunked upstream while advertising 1.0 downstream.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Cannot call write() after write_eof()
- Cannot call write() before prepare()
- Setting charset for application/octet-stream doesn't make se
- Unsupported type for last_modified: {type(value).__name__}
- Unsupported etag type: {type(value)}. etag must be str, ETag
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/0a065c1d8f02ed62.
Report an issue: GitHub.