{"record":{"id":"c12588462776faa5","repo":"python/cpython","slug":"can-t-have-text-and-binary-mode-at-once","errorCode":null,"errorMessage":"can't have text and binary mode at once","messagePattern":"can't have text and binary mode at once","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":217,"sourceCode":"        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\")\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 \"\") +","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L199-L235","documentation":"Raised by io.open() as a ValueError when the mode string contains both 't' and 'b'. Text mode and binary mode are mutually exclusive: text mode decodes bytes through an encoding with newline translation, binary mode returns raw bytes, so both cannot apply at once.","triggerScenarios":"open('f', 'rtb'), 'wtb', 'r+t+b' — typically a mode assembled programmatically where a default 't' is concatenated onto a user-supplied 'rb'/'wb', or a hand-typed 'rtb'.","commonSituations":"Mode-building helpers that always append 't' (or default to text) and then receive a base mode that already contains 'b'; merging CLI flags (-t and -b both accepted); documentation examples copied from code that constructed mode strings by concatenation.","solutions":["Pick one: 'rb'/'wb'/'ab' (+ 'b' variants) for bytes, or 'r'/'w'/'a' with optional 't' for str.","In mode-building code, derive binary/text from a single variable, not two independent flags that can both be true.","Validate composed modes against a whitelist before calling open()."],"exampleFix":"// before\nmode = base_mode + ('t' if text_default else '')   # base 'rb' -> 'rbt'\nopen(path, mode)\n\n// after\nif 'b' in base_mode:\n    mode = base_mode            # binary stays binary\nelse:\n    mode = base_mode + ('t' if force_t else '')\nopen(path, mode)","handlingStrategy":"validation","validationCode":"def build_mode(base: str, binary: bool, update: bool = False) -> str:\n    assert base in ('r', 'w', 'a', 'x')\n    return base + ('b' if binary else 't' if False else '') + ('+' if update else '')\n# single `binary` boolean makes t/b mutually exclusive by construction","typeGuard":"def mode_consistent(mode: str) -> bool:\n    s = set(mode)\n    return not ('t' in s and 'b' in s)","tryCatchPattern":null,"preventionTips":["Derive 'b'/'t' from one boolean, never two independent flags.","Prefer omitting 't' — text is the default; only 'b' needs to be explicit.","Whitelist-validate assembled mode strings before open()."],"tags":["io","open","mode","valueerror","text-io","binary-io"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}