{"id":"fd76904278088613","repo":"encode/httpx","slug":"setting-encoding-after-text-has-been-accessed-is","errorCode":null,"errorMessage":"Setting encoding after `text` has been accessed is not allowed.","messagePattern":"Setting encoding after `text` has been accessed is not allowed\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"httpx/_models.py","lineNumber":683,"sourceCode":"            encoding = self.charset_encoding\n            if encoding is None or not _is_known_encoding(encoding):\n                if isinstance(self.default_encoding, str):\n                    encoding = self.default_encoding\n                elif hasattr(self, \"_content\"):\n                    encoding = self.default_encoding(self._content)\n            self._encoding = encoding or \"utf-8\"\n        return self._encoding\n\n    @encoding.setter\n    def encoding(self, value: str) -> None:\n        \"\"\"\n        Set the encoding to use for decoding the byte content into text.\n\n        If the `text` attribute has been accessed, attempting to set the\n        encoding will throw a ValueError.\n        \"\"\"\n        if hasattr(self, \"_text\"):\n            raise ValueError(\n                \"Setting encoding after `text` has been accessed is not allowed.\"\n            )\n        self._encoding = value\n\n    @property\n    def charset_encoding(self) -> str | None:\n        \"\"\"\n        Return the encoding, as specified by the Content-Type header.\n        \"\"\"\n        content_type = self.headers.get(\"Content-Type\")\n        if content_type is None:\n            return None\n\n        return _parse_content_type_charset(content_type)\n\n    def _get_content_decoder(self) -> ContentDecoder:\n        \"\"\"\n        Returns a decoder instance which can be used to decode the raw byte","sourceCodeStart":665,"sourceCodeEnd":701,"githubUrl":"https://github.com/encode/httpx/blob/b5addb64f0161ff6bfe94c124ef76f6a1fba5254/httpx/_models.py#L665-L701","documentation":"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.","triggerScenarios":"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.","commonSituations":"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`.","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."],"exampleFix":"// before\nprint(response.text)\nresponse.encoding = 'latin-1'  # ValueError\n\n// after\nresponse.encoding = 'latin-1'\nprint(response.text)","handlingStrategy":"validation","validationCode":"def can_set_encoding(resp: httpx.Response) -> bool:\n    return not hasattr(resp, '_text')","typeGuard":"import httpx\n\ndef encoding_is_locked(resp: httpx.Response) -> bool:\n    return hasattr(resp, '_text')","tryCatchPattern":"try:\n    response.encoding = 'latin-1'\nexcept ValueError:\n    del response._text  # invalidate cache, then retry\n    response.encoding = 'latin-1'","preventionTips":["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."],"tags":["encoding","response","value-error","text-decoding"],"analyzedSha":"b5addb64f0161ff6bfe94c124ef76f6a1fba5254","analyzedAt":"2026-08-04T19:32:56.768Z","schemaVersion":2}