aio-libs/aiohttp · error · RuntimeError
Setting charset for application/octet-stream doesn't make se
Error message
Setting charset for application/octet-stream doesn't make sense, setup content_type first
What it means
StreamResponse (and Response) default their content_type to application/octet-stream. The charset setter refuses to attach a charset to this binary type, because a charset parameter is meaningless for opaque binary data and would mislead clients. You must set a meaningful text content_type (e.g. text/plain, application/json) before assigning charset.
Source
Thrown at aiohttp/web_response.py:240
# Just a placeholder for adding setter
return super().content_type
@content_type.setter
def content_type(self, value: str) -> None:
self.content_type # read header values if needed
self._content_type = str(value)
self._generate_content_type_header()
@property
def charset(self) -> str | None:
# Just a placeholder for adding setter
return super().charset
@charset.setter
def charset(self, value: str | None) -> None:
ctype = self.content_type # read header values if needed
if ctype == "application/octet-stream":
raise RuntimeError(
"Setting charset for application/octet-stream "
"doesn't make sense, setup content_type first"
)
assert self._content_dict is not None
if value is None:
self._content_dict.pop("charset", None)
else:
self._content_dict["charset"] = str(value).lower()
self._generate_content_type_header()
@property
def last_modified(self) -> datetime.datetime | None:
"""The value of Last-Modified HTTP header, or None.
This header is represented as a `datetime` object.
"""
return parse_http_date(self._headers.get(hdrs.LAST_MODIFIED))
View on GitHub (pinned to c0ef574e29)
Solutions
- Set a text content_type before charset: resp = StreamResponse(content_type='text/plain') then resp.charset = 'utf-8'.
- If you have static text/JSON, use Response(text=...) which auto-sets content_type and charset for you.
- If you must override on an existing response, assign resp.content_type = 'application/json' first, then resp.charset.
Example fix
# before resp = StreamResponse() resp.charset = 'utf-8' # raises RuntimeError # after resp = StreamResponse(content_type='text/plain') resp.charset = 'utf-8'
Defensive patterns
Strategy: validation
Validate before calling
def safe_set_charset(resp, charset):
if resp.content_type == 'application/octet-stream':
resp.content_type = 'text/plain' # or your intended text type
resp.charset = charset Type guard
def is_text_content_type(ct: str) -> bool:
return not ct.startswith('application/octet-stream') and (
ct.startswith('text/') or 'json' in ct or 'xml' in ct or 'charset' in ct
) Prevention
- Always pass content_type= to StreamResponse when you intend to set charset.
- Prefer Response(text=...) for text/JSON bodies — it sets content_type and charset for you.
- Never assume the default content_type is a text type; it defaults to application/octet-stream.
When it happens
Trigger: Calling `resp.charset = 'utf-8'` on a freshly constructed StreamResponse without first setting content_type, or passing content_type='application/octet-stream' and then assigning charset. The check at line 239 compares ctype == 'application/octet-stream' exactly.
Common situations: Devs copy a Response(text=...) example into a manual StreamResponse and try to set charset directly; serving dynamically generated JSON/text as a stream; calling `resp.charset = 'utf-8'` after `StreamResponse()` with no content_type argument.
Related errors
- charset must not be in content_type argument
- passing both Content-Type header and content_type or charset
- Got more than {limit} bytes when reading: {line!r}.
- 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/f9e9ce57e36556ba.json.
Report an issue: GitHub.