aio-libs/aiohttp · error · RuntimeError
Content length is set automatically
Error message
Content length is set automatically
What it means
Response.content_length is a read-only computed property: its value is derived from the body length, compressed body, or Payload size (lines 657-674). The setter unconditionally raises RuntimeError because manually setting it would desynchronize the header from the actual bytes sent.
Source
Thrown at aiohttp/web_response.py:678
return None
if hdrs.CONTENT_LENGTH in self._headers:
return int(self._headers[hdrs.CONTENT_LENGTH])
if self._compressed_body is not None:
# Return length of the compressed body
return len(self._compressed_body)
elif isinstance(self._body, Payload):
# A payload without content length, or a compressed payload
return None
elif self._body is not None:
return len(self._body)
else:
return 0
@content_length.setter
def content_length(self, value: int | None) -> None:
raise RuntimeError("Content length is set automatically")
async def write_eof(self, data: bytes = b"") -> None:
if self._eof_sent:
return
if self._compressed_body is None:
body = self._body
else:
body = self._compressed_body
assert not data, f"data arg is not supported, got {data!r}"
assert self._req is not None
assert self._payload_writer is not None
if body is None or self._must_be_empty_body:
await super().write_eof()
elif isinstance(self._body, Payload):
try:
await self._body.write(self._payload_writer)
finally:
await self._body.close()View on GitHub (pinned to c0ef574e29)
Solutions
- Let aiohttp compute content_length automatically from the body.
- If you need a specific length, set the body to exactly that many bytes (or use a Payload with .size).
- For low-level control use StreamResponse (whose content_length setter is allowed), not Response.
Example fix
# before resp = Response(text='hi') resp.content_length = 2 # raises RuntimeError on Response # after resp = Response(text='hi') # content_length computed automatically as 2
Defensive patterns
Strategy: validation
Validate before calling
# Response.content_length is read-only; do not assign.
# If you need manual length control, use StreamResponse:
# resp = StreamResponse(headers={'Content-Length': str(n)}) Prevention
- Never assign to Response.content_length — it is computed from the body.
- Use StreamResponse if you must set a content length manually.
- For Payload objects, set .size to influence the computed length.
When it happens
Trigger: Calling `resp.content_length = 123` on a Response instance. (Note: StreamResponse.content_length setter at line 208-209 does allow assignment; only the Response subclass forbids it.)
Common situations: Trying to pre-set a content length before streaming; copying StreamResponse code onto a Response;HEAD/304 handling where devs attempt to force a length.
Related errors
- chunked can not be set if Content-Length header is set
- Got more than {limit} bytes when reading: {line!r}.
- 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@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/171450abd88167cb.json.
Report an issue: GitHub.