encode/httpx · error · ValueError
Setting encoding after `text` has been accessed is not allow
Error message
Setting encoding after `text` has been accessed is not allowed.
What it means
Raised as `ValueError` by the `encoding` setter when `self._text` already exists. httpx caches the decoded text on first access; once cached, changing the encoding would not retroactively re-decode the cached string, so the setter refuses to silently produce inconsistent state. Set the encoding before any `.text`/`.json()`-style decode.
Source
Thrown at httpx/_models.py:683
encoding = self.charset_encoding
if encoding is None or not _is_known_encoding(encoding):
if isinstance(self.default_encoding, str):
encoding = self.default_encoding
elif hasattr(self, "_content"):
encoding = self.default_encoding(self._content)
self._encoding = encoding or "utf-8"
return self._encoding
@encoding.setter
def encoding(self, value: str) -> None:
"""
Set the encoding to use for decoding the byte content into text.
If the `text` attribute has been accessed, attempting to set the
encoding will throw a ValueError.
"""
if hasattr(self, "_text"):
raise ValueError(
"Setting encoding after `text` has been accessed is not allowed."
)
self._encoding = value
@property
def charset_encoding(self) -> str | None:
"""
Return the encoding, as specified by the Content-Type header.
"""
content_type = self.headers.get("Content-Type")
if content_type is None:
return None
return _parse_content_type_charset(content_type)
def _get_content_decoder(self) -> ContentDecoder:
"""
Returns a decoder instance which can be used to decode the raw byteView on GitHub (pinned to b5addb64f0)
Solutions
- Set `response.encoding = '...'` BEFORE the first `response.text` access.
- If you must re-decode, delete the cache: `del response._text` (private) then set encoding, or re-request.
- Pass `default_encoding=` to the client/request to control autodetection up front instead of mutating post-hoc.
- Decode bytes yourself: `response.content.decode('latin-1')` when you need a one-off alternative encoding.
Example fix
// before print(response.text) response.encoding = 'latin-1' # ValueError // after response.encoding = 'latin-1' print(response.text)
Defensive patterns
Strategy: validation
Validate before calling
def can_set_encoding(resp: httpx.Response) -> bool:
return not hasattr(resp, '_text') Type guard
import httpx
def encoding_is_locked(resp: httpx.Response) -> bool:
return hasattr(resp, '_text') Try / catch
try:
response.encoding = 'latin-1'
except ValueError:
del response._text # invalidate cache, then retry
response.encoding = 'latin-1' Prevention
- Set encoding before the first .text access.
- Pass default_encoding= to control autodetection upfront.
- For one-off decodes, use response.content.decode(enc) instead of mutating .encoding.
When it happens
Trigger: Calling `response.text` (or anything that calls the `text` property) and then `response.encoding = 'latin-1'`. Also indirectly via helper functions that read `.text` then attempt to override encoding for a retry.
Common situations: Charm/charset-autodetection loops that read text then try to fix the encoding; porting `requests` code that mutated `r.encoding` freely; codecs mismatched against a mislabelled `Content-Type`.
Related errors
- '.elapsed' may only be accessed after the response has been
- The request instance has not been set on this response.
- Attempted to access streaming response content, without havi
- Cannot call `raise_for_status` as the request instance has n
- Attempted to read or stream some content, but the content ha
AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04).
Data as JSON: /data/errors/fd76904278088613.json.
Report an issue: GitHub.