{"id":"171450abd88167cb","repo":"aio-libs/aiohttp","slug":"content-length-is-set-automatically","errorCode":null,"errorMessage":"Content length is set automatically","messagePattern":"Content length is set automatically","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/web_response.py","lineNumber":678,"sourceCode":"            return None\n\n        if hdrs.CONTENT_LENGTH in self._headers:\n            return int(self._headers[hdrs.CONTENT_LENGTH])\n\n        if self._compressed_body is not None:\n            # Return length of the compressed body\n            return len(self._compressed_body)\n        elif isinstance(self._body, Payload):\n            # A payload without content length, or a compressed payload\n            return None\n        elif self._body is not None:\n            return len(self._body)\n        else:\n            return 0\n\n    @content_length.setter\n    def content_length(self, value: int | None) -> None:\n        raise RuntimeError(\"Content length is set automatically\")\n\n    async def write_eof(self, data: bytes = b\"\") -> None:\n        if self._eof_sent:\n            return\n        if self._compressed_body is None:\n            body = self._body\n        else:\n            body = self._compressed_body\n        assert not data, f\"data arg is not supported, got {data!r}\"\n        assert self._req is not None\n        assert self._payload_writer is not None\n        if body is None or self._must_be_empty_body:\n            await super().write_eof()\n        elif isinstance(self._body, Payload):\n            try:\n                await self._body.write(self._payload_writer)\n            finally:\n                await self._body.close()","sourceCodeStart":660,"sourceCodeEnd":696,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/web_response.py#L660-L696","documentation":"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.","triggerScenarios":"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.)","commonSituations":"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.","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."],"exampleFix":"# before\nresp = Response(text='hi')\nresp.content_length = 2  # raises RuntimeError on Response\n\n# after\nresp = Response(text='hi')  # content_length computed automatically as 2","handlingStrategy":"validation","validationCode":"# Response.content_length is read-only; do not assign.\n# If you need manual length control, use StreamResponse:\n# resp = StreamResponse(headers={'Content-Length': str(n)})","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["http","headers","content-length","response","readonly"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}