{"record":{"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/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/web_response.py#L660-L696","documentation":"Raised by the Response.content_length setter, which is intentionally a no-op that always raises. Content-Length is computed automatically from the body (len of bytes, compressed body, or 0 for None) during preparation; allowing manual override would desync the header from the actual bytes written.","triggerScenarios":"Calling `resp.content_length = 1234` anywhere in handler code. Often a copy-paste from setting other headers, or attempting to pre-declare length on a streaming response.","commonSituations":"Developers used to setting Content-Length manually in other frameworks; trying to fix a streaming response that has no length by setting the property; refactoring that mistakenly assigns to the property.","solutions":["Provide the full body up front via `body=`/`text=` and let aiohttp compute the length.","For fixed-size streaming, buffer the chunks and pass the joined bytes as body.","To suppress Content-Length (e.g. chunked), use a StreamResponse with chunked encoding rather than mutating content_length.","Remove the assignment entirely; the property is read-only by design."],"exampleFix":"// before\nresp = Response(body=data)\nresp.content_length = len(data)  # RuntimeError\n\n// after\nresp = Response(body=data)  # content_length is auto-derived; do not set","handlingStrategy":"validation","validationCode":"# content_length is read-only; never assign to it.\n# Provide the full body and let aiohttp compute length.\nresp = Response(body=data)\nlength = resp.content_length  # read, do not write","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never assign to resp.content_length — it is computed from the body.","Provide the full body up front for fixed-length responses.","Use StreamResponse with chunked encoding when length is unknown.","Treat content_length as read-only in code review."],"tags":["aiohttp","web-response","content-length","read-only","body"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}