{"record":{"id":"f9e9ce57e36556ba","repo":"aio-libs/aiohttp","slug":"setting-charset-for-application-octet-stream-doesn","errorCode":null,"errorMessage":"Setting charset for application/octet-stream doesn't make sense, setup content_type first","messagePattern":"Setting charset for application/octet-stream doesn't make sense, setup content_type first","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/web_response.py","lineNumber":240,"sourceCode":"        # Just a placeholder for adding setter\n        return super().content_type\n\n    @content_type.setter\n    def content_type(self, value: str) -> None:\n        self.content_type  # read header values if needed\n        self._content_type = str(value)\n        self._generate_content_type_header()\n\n    @property\n    def charset(self) -> str | None:\n        # Just a placeholder for adding setter\n        return super().charset\n\n    @charset.setter\n    def charset(self, value: str | None) -> None:\n        ctype = self.content_type  # read header values if needed\n        if ctype == \"application/octet-stream\":\n            raise RuntimeError(\n                \"Setting charset for application/octet-stream \"\n                \"doesn't make sense, setup content_type first\"\n            )\n        assert self._content_dict is not None\n        if value is None:\n            self._content_dict.pop(\"charset\", None)\n        else:\n            self._content_dict[\"charset\"] = str(value).lower()\n        self._generate_content_type_header()\n\n    @property\n    def last_modified(self) -> datetime.datetime | None:\n        \"\"\"The value of Last-Modified HTTP header, or None.\n\n        This header is represented as a `datetime` object.\n        \"\"\"\n        return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED))\n","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/web_response.py#L222-L258","documentation":"Raised by Response.charset setter when the current content_type is the default 'application/octet-stream'. aiohttp refuses to attach a charset to a binary mime type because the Content-Type header would become semantically meaningless (e.g. 'application/octet-stream; charset=utf-8'). You must first set a text-oriented content_type so the charset is meaningful.","triggerScenarios":"Calling `resp.charset = 'utf-8'` on a freshly constructed `Response()` (or StreamResponse) without having set `resp.content_type` to a text type first. Also triggered by `Response(content_type='application/octet-stream', charset='utf-8')` if the content_type setter leaves the default, or by mutating charset after resetting content_type back to the default.","commonSituations":"Building a generic Response and forgetting to pass `content_type='text/plain'` (or `text/html`, `application/json`) before assigning charset. Migrating code from explicitly-typed responses to a base StreamResponse and dropping the content_type line. The error is a deliberate guard because octet-stream bodies are bytes and charset is meaningless there.","solutions":["Set `resp.content_type = 'text/html'` (or another text/* or application/json type) BEFORE assigning `resp.charset`.","Construct the response with the content_type up front: `Response(text=body, content_type='text/html; charset=utf-8')` or pass `text=` which auto-sets both content_type and charset.","If you genuinely have binary data, do not set a charset at all — leave the default octet-stream.","Avoid string-concatenating '; charset=...' into content_type manually; use the dedicated charset property after a valid text content_type."],"exampleFix":"// before\nresp = StreamResponse()\nresp.charset = 'utf-8'  # RuntimeError\n\n// after\nresp = StreamResponse()\nresp.content_type = 'text/plain'\nresp.charset = 'utf-8'","handlingStrategy":"validation","validationCode":"def set_charset(resp, charset):\n    if resp.content_type in ('application/octet-stream', None):\n        resp.content_type = 'text/plain'  # or another text type\n    resp.charset = charset","typeGuard":"def is_text_content_type(ctype: str) -> bool:\n    return ctype.startswith('text/') or ctype in (\n        'application/json', 'application/javascript',\n        'application/xml', 'application/xhtml+xml',\n    )","tryCatchPattern":null,"preventionTips":["Set content_type to a text/* or application/json type before assigning charset.","Prefer Response(text=...) which sets content_type and charset together.","Treat octet-stream bodies as bytes-only — never attach a charset.","In helpers, normalize content_type first, then charset."],"tags":["aiohttp","web-response","content-type","charset","http-headers"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}