{"record":{"id":"38d20732913f8be2","repo":"python/cpython","slug":"invalid-mode-r","errorCode":null,"errorMessage":"invalid mode: %r","messagePattern":"invalid mode: %r","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":199,"sourceCode":"    through which the standard file operations such as reading and writing\n    are performed. When open() is used to open a file in a text mode ('w',\n    'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open\n    a file in a binary mode, the returned class varies: in read binary\n    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\")","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L181-L217","documentation":"Raised by io.open() when the mode argument is not a str. open() validates argument types before touching the filesystem; any non-string mode (None, bytes, int) triggers this TypeError. Note this is about the type, not the contents — a malformed string like 'z' raises ValueError('invalid mode') instead.","triggerScenarios":"open('f.txt', None), open('f.txt', b'r'), open('f.txt', 0), or a typo like open('f.txt', modes) where modes is a set/list of characters built elsewhere. Also passing mode as a keyword with the wrong variable, e.g. open(path, mode=m.group(1)) where the regex group is None on no-match.","commonSituations":"Mode computed dynamically (from config or CLI flags) and the computation silently yields None; refactoring that reorders positional args so a non-mode value lands in the mode slot; copy-paste from bytes-literal code (b'r') in porting exercises.","solutions":["Pass a str mode such as 'r', 'w', 'a', 'x', 'rb', 'w+b', etc.","If mode is computed, give it a default ('r' is open()'s default) and assert isinstance(mode, str) near the computation.","Fix the None-returning expression (e.g. regex .group() vs .group(0), dict.get with default) that feeds the mode parameter."],"exampleFix":"// before\nmode = flags.get('write') and 'w'      # None when 'write' missing\nopen('out.txt', mode)                    # TypeError: invalid mode: None\n\n// after\nmode = 'w' if flags.get('write') else 'r'\nopen('out.txt', mode)","handlingStrategy":"validation","validationCode":"VALID_MODES = {'r','w','a','x','r+','w+','a+','x+','rb','wb','ab','xb','r+b','w+b','a+b','x+b','rt','wt','at','xt','r+t','w+t','a+t','x+t'}\n\nassert mode in VALID_MODES, f'unexpected mode {mode!r}'\nopen(path, mode)","typeGuard":"def is_valid_mode(mode) -> bool:\n    return (\n        isinstance(mode, str)\n        and set(mode) <= set('axrwb+t')\n        and len(mode) == len(set(mode))\n        and bool(set(mode) & set('rwax'))\n        and not ({'t','b'} <= set(mode))\n    )","tryCatchPattern":"try:\n    f = open(path, mode)\nexcept TypeError as e:\n    if 'invalid mode' in str(e):\n        mode = 'r'   # safe fallback\n        f = open(path, mode)\n    else:\n        raise","preventionTips":["Default mode explicitly (mode='r') in wrappers so it is never None.","Build modes only from a whitelist of complete strings ('rb', 'w+', ...), never by free-form concatenation.","Check regex group results for None before using them as mode."],"tags":["io","open","mode","typeerror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}