aio-libs/aiohttp · error · ValueError
chunked can not be set if Content-Length header is set
Error message
chunked can not be set if Content-Length header is set
What it means
Raised by ClientRequest._update_transfer_encoding() when chunked transfer encoding is being enabled but a Content-Length header is already present. A message cannot have both a Content-Length (fixed size) and chunked Transfer-Encoding (unknown size); they are mutually exclusive per HTTP semantics, so aiohttp raises ValueError.
Solutions
- For fixed-size bodies, let aiohttp compute Content-Length from the data and don't set it manually.
- For streaming/unknown-size bodies, remove any manual Content-Length header.
- If you set Content-Length, ensure the body is bytes/str with matching length and not a stream.
- Audit header construction to avoid stale Content-Length from a template.
Example fix
# before
headers['Content-Length'] = '100'
await session.post(url, data=async_gen(), headers=headers) # ValueError
# after — streaming body, no manual Content-Length
await session.post(url, data=async_gen(), headers={k:v for k,v in headers.items() if k.lower()!='content-length'}) Defensive patterns
Strategy: validation
Validate before calling
def strip_conflicting_length(headers, body):
# streaming/unknown-size body cannot have a preset Content-Length
if not isinstance(body, (bytes, bytearray, str)):
headers.pop('Content-Length', None)
return headers Type guard
def body_and_headers_consistent(headers, body) -> bool:
streaming = not isinstance(body, (bytes, bytearray, str, type(None)))
return not (streaming and any(k.lower() == 'content-length' for k in headers)) Try / catch
try:
await session.post(url, data=stream_gen, headers=headers)
except ValueError as e:
if 'Content-Length header is set' in str(e):
headers = {k:v for k,v in headers.items() if k.lower() != 'content-length'}
await session.post(url, data=stream_gen, headers=headers)
else:
raise Prevention
- Don't set Content-Length when the body is a generator/stream.
- Let aiohttp compute Content-Length for bytes/str bodies.
- Filter Content-Length out of templated header dicts before streaming requests.
When it happens
Trigger: Setting headers['Content-Length']='123' AND triggering chunked mode (via a streaming body, compress=True, or chunked=True). _update_transfer_encoding sees self.chunked True and Content-Length in headers, and raises ValueError.
Common situations: Pre-setting Content-Length for a body whose actual size is unknown (stream); copy-pasting headers that include Content-Length while passing a generator/async generator body; mixing fixed-length assumptions with chunked producers.
Related errors
- chunked can not be set if "Transfer-Encoding: chunked"…
- Invalid Content-Length header
- compress can not be set if Content-Encoding header is set
- You can't enable chunked encoding when a content length is…
- You can't set content length when chunked encoding is enable
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/199e512a479f3673.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/client_reqrep.py:1235
)
self.compress = compress if isinstance(compress, str) else "deflate"
self.headers[hdrs.CONTENT_ENCODING] = self.compress
self.chunked = True # enable chunked, no need to deal with length
def _update_transfer_encoding(self) -> None:
"""Analyze transfer-encoding header."""
te = self.headers.get(hdrs.TRANSFER_ENCODING, "").lower()
if "chunked" in te:
if self.chunked:
raise ValueError(
"chunked can not be set "
'if "Transfer-Encoding: chunked" header is set'
)
elif self.chunked:
if hdrs.CONTENT_LENGTH in self.headers:
raise ValueError(
"chunked can not be set if Content-Length header is set"
)
self.headers[hdrs.TRANSFER_ENCODING] = "chunked"
def _update_body_from_data(self, body: Any) -> None:
"""Update request body from data."""
if body is None:
self._body = self._EMPTY_BODY
# Set Content-Length to 0 when body is None for methods that expect a body
if (
self.method not in self.GET_METHODS
and not self.chunked
and hdrs.CONTENT_LENGTH not in self.headers
):
self.headers[hdrs.CONTENT_LENGTH] = "0"
return
View on GitHub (pinned to d041d4d0fd)