Python
OSError
print function
error handling
troubleshooting

OSError raw write returned invalid length when using print in python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

OSError: raw write() returned invalid length usually means the stream under print() is broken, not that print() itself is wrong. Python expected the underlying raw stream to report the number of bytes it wrote, but the stream returned an impossible value or otherwise violated the file-like object contract.

What print() Writes To

print() ultimately writes text to sys.stdout unless you override the file argument. In a normal terminal, sys.stdout is a TextIOWrapper layered on top of a buffered binary stream and then a raw file descriptor.

If one of those lower layers is replaced with a custom object that implements write() incorrectly, Python can raise this error.

A raw write() method is expected to return:

  • the number of bytes written, as an integer
  • or None only in specific non-blocking situations, depending on the layer

Returning an impossible length breaks the contract.

A Minimal Broken Example

The following example intentionally implements a bad raw stream. It reproduces the failure pattern by returning a length larger than the number of bytes received.

python
1import io
2
3
4class BrokenRaw(io.RawIOBase):
5    def writable(self):
6        return True
7
8    def write(self, b):
9        return len(b) + 1
10
11
12raw = BrokenRaw()
13buffered = io.BufferedWriter(raw)
14text = io.TextIOWrapper(buffered, encoding="utf-8")
15
16text.write("hello\n")
17text.flush()

The stream claims it wrote more bytes than Python handed to it, so the I/O stack rejects the result.

Where This Happens in Real Code

In production code, the error tends to appear in unusual output environments, such as:

  • custom logging or stdout redirection wrappers
  • embedded interpreters
  • notebook or REPL integrations
  • subprocess pipes with incorrect wrappers
  • low-level device or socket abstractions pretending to be file objects

The clue is that the problem sits below print(). If print() fails only in one environment and works in a regular terminal, inspect whatever replaced sys.stdout.

Validate the Current Stream

A fast debugging step is to inspect sys.stdout and its underlying buffer objects.

python
1import sys
2
3print(type(sys.stdout))
4print(repr(sys.stdout))
5print(getattr(sys.stdout, "buffer", None))

If sys.stdout is a custom proxy or wrapper, look at its write() implementation. That is where the contract is often violated.

Another useful check is to bypass the text wrapper and write directly to stderr or the original stdout to see whether the failure is specific to the replaced stream.

python
1import sys
2
3sys.__stdout__.write("debug output\n")
4sys.__stdout__.flush()

If this works while print() fails, the replacement stdout is the likely culprit.

The Correct Contract for Raw Streams

If you implement a raw writable stream yourself, write() should return the number of bytes actually written.

python
1import io
2
3
4class CollectingRaw(io.RawIOBase):
5    def __init__(self):
6        self.data = bytearray()
7
8    def writable(self):
9        return True
10
11    def write(self, b):
12        self.data.extend(b)
13        return len(b)
14
15
16raw = CollectingRaw()
17buffered = io.BufferedWriter(raw)
18text = io.TextIOWrapper(buffered, encoding="utf-8")
19
20print("works", file=text)
21text.flush()
22print(raw.data.decode("utf-8"))

This version behaves correctly because the raw layer reports exactly how many bytes it accepted.

Watch for Partial Writes and Non-Blocking Behavior

The situation gets more subtle when your stream wraps sockets or non-blocking devices. Partial writes can be legitimate at some layers, but the stream type must support them correctly. If you build a file-like wrapper manually, it is easy to violate the expectations of BufferedWriter or TextIOWrapper.

That is why it is often safer to reuse the standard io abstractions rather than implementing low-level stream behavior from scratch.

When the Error Appears Only With print()

print() adds text encoding, separators, and line endings on top of the text stream. A broken raw layer may not show up until text buffering flushes down to bytes. That can make the error look surprising, because the visible failure is at print() even though the real defect is much lower.

This is also why replacing print() with logging sometimes “fixes” the symptom: the logging handler may write through a different stream.

Common Pitfalls

A common mistake is implementing a custom stream that returns the wrong byte count from write().

Another mistake is replacing sys.stdout with an object that looks file-like at the surface but does not obey the io layer contracts fully.

Developers also forget that text streams and raw byte streams have different responsibilities. Encoding belongs in TextIOWrapper; raw streams should deal in bytes and accurate write counts.

Finally, do not debug this as a formatting bug in print(). The failure is usually in the underlying stream implementation.

Summary

  • The error means the raw stream beneath print() reported an invalid write length.
  • 'print() is usually not the real problem; the stream implementation is.'
  • Inspect sys.stdout and any custom redirection or wrapper code.
  • A correct raw write() must report the number of bytes actually written.
  • Reuse Python's standard io stack when possible instead of building low-level stream layers by hand.

Course illustration
Course illustration

All Rights Reserved.