{"record":{"id":"a332ff7fa202653e","repo":"python/cpython","slug":"invalid-encoding-r","errorCode":null,"errorMessage":"invalid encoding: %r","messagePattern":"invalid encoding: %r","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":203,"sourceCode":"    mode, it returns a BufferedReader; in write binary and append binary\n    modes, it returns a BufferedWriter, and in read/write mode, it returns\n    a BufferedRandom.\n\n    It is also possible to use a string or bytearray as a file for both\n    reading and writing. For strings StringIO can be used like a file\n    opened in a text mode, and for bytes a BytesIO can be used like a file\n    opened in a binary mode.\n    \"\"\"\n    if not isinstance(file, int):\n        file = os.fspath(file)\n    if not isinstance(file, (str, bytes, int)):\n        raise TypeError(\"invalid file: %r\" % file)\n    if not isinstance(mode, str):\n        raise TypeError(\"invalid mode: %r\" % mode)\n    if not isinstance(buffering, int):\n        raise TypeError(\"invalid buffering: %r\" % buffering)\n    if encoding is not None and not isinstance(encoding, str):\n        raise TypeError(\"invalid encoding: %r\" % encoding)\n    if errors is not None and not isinstance(errors, str):\n        raise TypeError(\"invalid errors: %r\" % errors)\n    modes = set(mode)\n    if modes - set(\"axrwb+t\") or len(mode) > len(modes):\n        raise ValueError(\"invalid mode: %r\" % mode)\n    creating = \"x\" in modes\n    reading = \"r\" in modes\n    writing = \"w\" in modes\n    appending = \"a\" in modes\n    updating = \"+\" in modes\n    text = \"t\" in modes\n    binary = \"b\" in modes\n    if text and binary:\n        raise ValueError(\"can't have text and binary mode at once\")\n    if creating + reading + writing + appending > 1:\n        raise ValueError(\"can't have read/write/append mode at once\")\n    if not (creating or reading or writing or appending):\n        raise ValueError(\"must have exactly one of read/write/append mode\")","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L185-L221","documentation":"Raised by io.open() when the encoding argument is supplied and is neither None nor a str. encoding is only meaningful in text mode, and the validator checks its type up front. Passing None (the default) is fine; any other non-string (bytes, list, int) raises this TypeError.","triggerScenarios":"open('f', 'r', encoding=b'utf-8'), encoding=['utf-8'], or encoding pulled from a config/env layer that returns a non-string (e.g. a codecs.CodecInfo object, or None-vs-missing sentinel mishandling such as encoding=flag or None chains producing False).","commonSituations":"Encoding taken from environment or config that yields bytes (common in Py2-to-Py3 ports); passing the result of codecs.lookup() (a CodecInfo) instead of its .name; boolean expressions like encoding=use_utf8 and 'utf-8' evaluating to False.","solutions":["Pass a codec name string ('utf-8', 'latin-1', ...) or None.","If the value may come from bytes config, decode it first: encoding=cfg_bytes.decode().","For CodecInfo objects, pass codec.name instead of the object.","Fix conditional expressions: encoding='utf-8' if use_utf8 else None."],"exampleFix":"// before\nenc = os.environb.get(b'ENC')       # bytes or None\nopen('f', encoding=enc)             # TypeError when bytes\n\n// after\nenc = os.environb.get(b'ENC', b'utf-8').decode('ascii')\nopen('f', encoding=enc)","handlingStrategy":"type-guard","validationCode":"if encoding is not None and not isinstance(encoding, str):\n    encoding = str(encoding)   # e.g. decode bytes or take codec.name\nopen(path, encoding=encoding)","typeGuard":"def valid_encoding(enc) -> bool:\n    return enc is None or isinstance(enc, str)","tryCatchPattern":"try:\n    open(path, encoding=enc)\nexcept TypeError as e:\n    if 'invalid encoding' in str(e) and isinstance(enc, (bytes, bytearray)):\n        open(path, encoding=bytes(enc).decode('ascii'))\n    else:\n        raise","preventionTips":["Decode bytes-sourced encoding names at the config boundary.","Pass codec.name for codecs.lookup results.","Write conditional encoding args as 'x' if cond else None, never cond and 'x'."],"tags":["io","open","encoding","typeerror","text-io"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}