{"record":{"id":"bbb21f22261d30b2","repo":"python/cpython","slug":"can-t-have-unbuffered-text-i-o","errorCode":null,"errorMessage":"can't have unbuffered text I/O","messagePattern":"can't have unbuffered text I/O","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":253,"sourceCode":"                 (reading and \"r\" or \"\") +\n                 (writing and \"w\" or \"\") +\n                 (appending and \"a\" or \"\") +\n                 (updating and \"+\" or \"\"),\n                 closefd, opener=opener)\n    result = raw\n    try:\n        line_buffering = False\n        if buffering == 1 or buffering < 0 and raw._isatty_open_only():\n            buffering = -1\n            line_buffering = True\n        if buffering < 0:\n            buffering = max(min(raw._blksize, 8192 * 1024), DEFAULT_BUFFER_SIZE)\n        if buffering < 0:\n            raise ValueError(\"invalid buffering size\")\n        if buffering == 0:\n            if binary:\n                return result\n            raise ValueError(\"can't have unbuffered text I/O\")\n        if updating:\n            buffer = BufferedRandom(raw, buffering)\n        elif creating or writing or appending:\n            buffer = BufferedWriter(raw, buffering)\n        elif reading:\n            buffer = BufferedReader(raw, buffering)\n        else:\n            raise ValueError(\"unknown mode: %r\" % mode)\n        result = buffer\n        if binary:\n            return result\n        encoding = text_encoding(encoding)\n        text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering)\n        result = text\n        text.mode = mode\n        return result\n    except:\n        result.close()","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L235-L271","documentation":"Raised by io.open() as a ValueError when buffering == 0 is requested in text mode. True unbuffered I/O only exists at the byte level; TextIOWrapper fundamentally needs a buffer to decode multi-byte encodings and translate newlines, so buffering=0 is rejected for any mode containing 't' (or plain 'r'/'w'/'a').","triggerScenarios":"open('f.txt', 'w', buffering=0) or open('f', 'r', buffering=0). Also wrappers that accept an unbuffered=True flag and map it to buffering=0 regardless of mode. (In binary mode buffering=0 is legal and returns the raw FileIO.)","commonSituations":"Log writers wanting every write to hit disk immediately; porting C stdbuf/setvbuf-style unbuffered expectations to Python text files; performance-tuning cargo cult that sets buffering=0 globally.","solutions":["For text mode, use line buffering (buffering=1) or write + explicit f.flush() after each record.","Switch to binary mode ('wb') if you truly need unbuffered writes and can work with bytes.","For logs that must survive crashes, flush() plus os.fsync(f.fileno()) rather than buffering=0."],"exampleFix":"// before\nwith open('app.log', 'w', buffering=0) as f:   # ValueError: can't have unbuffered text I/O\n    f.write(line)\n\n// after\nwith open('app.log', 'w', buffering=1) as f:   # line buffered text I/O\n    f.write(line + '\\n')\n# durability variant: f.flush(); os.fsync(f.fileno())","handlingStrategy":"validation","validationCode":"def open_text(path, mode='w', unbuffered=False):\n    buffering = 1 if unbuffered else -1        # 0 is illegal for text\n    return open(path, mode, buffering=buffering, encoding='utf-8')","typeGuard":"def buffering_legal(mode: str, buffering: int) -> bool:\n    return not (buffering == 0 and 'b' not in mode)","tryCatchPattern":null,"preventionTips":["Use buffering=1 (line buffered) plus newline-terminated writes for 'immediate' text output.","Call f.flush() (and os.fsync for durability) instead of buffering=0 in text mode.","Reserve buffering=0 for binary mode only."],"tags":["io","open","buffering","text-io","valueerror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}