{"record":{"id":"261c7b97011012e2","repo":"python/cpython","slug":"raw-argument-must-be-writable","errorCode":null,"errorMessage":"\"raw\" argument must be writable.","messagePattern":"\"raw\" argument must be writable\\.","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":1256,"sourceCode":"        with self._read_lock:\n            if whence == 1:\n                pos -= len(self._read_buf) - self._read_pos\n            pos = _BufferedIOMixin.seek(self, pos, whence)\n            self._reset_read_buf()\n            return pos\n\nclass BufferedWriter(_BufferedIOMixin):\n\n    \"\"\"A buffer for a writeable sequential RawIO object.\n\n    The constructor creates a BufferedWriter for the given writeable raw\n    stream. If the buffer_size is not given, it defaults to\n    DEFAULT_BUFFER_SIZE.\n    \"\"\"\n\n    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):\n        if not raw.writable():\n            raise OSError('\"raw\" argument must be writable.')\n\n        _BufferedIOMixin.__init__(self, raw)\n        if buffer_size <= 0:\n            raise ValueError(\"invalid buffer size\")\n        self.buffer_size = buffer_size\n        self._write_buf = bytearray()\n        self._write_lock = Lock()\n\n    def writable(self):\n        return self.raw.writable()\n\n    def write(self, b):\n        if isinstance(b, str):\n            raise TypeError(\"can't write str to binary stream\")\n        with self._write_lock:\n            if self.closed:\n                raise ValueError(\"write to closed file\")\n            # XXX we can implement some more tricks to try and avoid","sourceCodeStart":1238,"sourceCodeEnd":1274,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L1238-L1274","documentation":"Raised by the BufferedWriter constructor when raw.writable() is False. BufferedWriter only wraps write-capable raw streams and enforces this at construction, raising OSError with the quoted-argument message. Mirrors the readable check on BufferedReader.","triggerScenarios":"io.BufferedWriter(os.fdopen(rfd, 'rb')) using a pipe read end; wrapping a file opened 'rb'; custom raw stream whose writable() defaults to False (RawIOBase default) because it was not overridden.","commonSituations":"Swapped pipe ends; passing a socket half that is shut down for writing (shutdown(SHUT_WR) makes writes invalid); custom sink classes forgetting to implement writable().","solutions":["Wrap a genuinely writable raw stream: files opened 'wb'/'ab', the pipe write end, or a writable socket.","Implement writable() -> True on custom raw stream classes.","Probe raw.writable() before constructing to produce a domain-specific error."],"exampleFix":"# before\nr, w = os.pipe()\nwriter = io.BufferedWriter(os.fdopen(r, 'rb'))  # read end -> OSError\n\n# after\nr, w = os.pipe()\nwriter = io.BufferedWriter(os.fdopen(w, 'wb'))","handlingStrategy":"validation","validationCode":"if not raw.writable():\n    raise ValueError(\"supplied raw stream does not support writing\")\nwriter = io.BufferedWriter(raw)","typeGuard":"def is_writable_raw(obj) -> bool:\n    return hasattr(obj, \"writable\") and callable(getattr(obj, \"write\")) and obj.writable()","tryCatchPattern":"try:\n    writer = io.BufferedWriter(raw)\nexcept OSError as e:\n    raise ValueError(f\"need the write end, got: {raw!r}\") from e","preventionTips":["Open destination files with 'wb'/'ab' before wrapping.","Don't shutdown(SHUT_WR) sockets you intend to write to.","Implement writable() -> True on custom sinks."],"tags":["python","io","buffered-writer","oserror","constructor","pipe"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}