{"record":{"id":"dedde04b5edd7902","repo":"python/cpython","slug":"must-have-exactly-one-of-read-write-append-mode","errorCode":null,"errorMessage":"must have exactly one of read/write/append mode","messagePattern":"must have exactly one of read/write/append mode","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":221,"sourceCode":"        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\")\n    if binary and encoding is not None:\n        raise ValueError(\"binary mode doesn't take an encoding argument\")\n    if binary and errors is not None:\n        raise ValueError(\"binary mode doesn't take an errors argument\")\n    if binary and newline is not None:\n        raise ValueError(\"binary mode doesn't take a newline argument\")\n    if binary and buffering == 1:\n        import warnings\n        warnings.warn(\"line buffering (buffering=1) isn't supported in binary \"\n                      \"mode, the default buffer size will be used\",\n                      RuntimeWarning, 2)\n    raw = FileIO(file,\n                 (creating and \"x\" or \"\") +\n                 (reading and \"r\" or \"\") +\n                 (writing and \"w\" or \"\") +\n                 (appending and \"a\" or \"\") +\n                 (updating and \"+\" or \"\"),\n                 closefd, opener=opener)","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L203-L239","documentation":"Raised by io.open() as a ValueError when the mode string contains none of the base operations r/w/a/x. open() requires exactly one base operation; auxiliary flags ('+', 'b', 't') alone do not define what to do with the file.","triggerScenarios":"open('f', 'b'), open('f', '+'), open('f', 't'), open('f', '') or open('f', '+b'). Typically a mode variable that ended up empty (e.g. ''.join of flags where the base letter was forgotten) or a default of None coerced to '' somewhere.","commonSituations":"Mode built from optional flags where the base flag is itself optional and absent: mode = ('r' if read else '') + 'b' with read=False gives 'b'; refactors that drop the base letter but keep '+' / 'b'; passing an empty string explicitly.","solutions":["Always include a base letter: 'r' is the default — use 'rb', 'r+b', or just omit mode for 'r'.","Give mode-building code a fallback base: base = 'r' if not (write or append) else ...","Assert the final mode intersects {'r','w','a','x'} before calling open()."],"exampleFix":"// before\nmode = ('b' if binary else '') + ('+' if rw else '')  # can be '' or 'b'\nopen(path, mode)\n\n// after\nbase = 'w' if create else 'r'\nmode = base + ('b' if binary else '') + ('+' if rw else '')\nopen(path, mode)","handlingStrategy":"validation","validationCode":"def build_mode(binary: bool = False, update: bool = False, base: str = 'r') -> str:\n    if base not in ('r', 'w', 'a', 'x'):\n        raise ValueError(f'base must be one of r/w/a/x, got {base!r}')\n    return base + ('b' if binary else '') + ('+' if update else '')","typeGuard":"def has_base_op(mode: str) -> bool:\n    return bool(set(mode) & {'r', 'w', 'a', 'x'})","tryCatchPattern":null,"preventionTips":["Always give mode-building helpers a non-optional base letter (default 'r').","Remember open() itself defaults mode='r' — omit the argument rather than passing '' or flags-only strings.","Assert the final composed mode is non-empty and contains a base letter."],"tags":["io","open","mode","valueerror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}