BrokenPipeError, what it means and how to fix it

A pipe (or socket) has two ends; this error means your program wrote to its end after the other end had been closed by its owner. The famous case is shell plumbing: python report.py | head prints a few lines, head exits satisfied, and the producer's next write lands in a pipe with no reader. The network case is identical in shape: the client disconnected, and the server's next send discovers it.

What it looks like

# at the shell:
#   python3 names.py | head -n 2

for name in load_a_million_names():
    print(name)               # head exits after 2 lines;
                              # the next print has no reader

BrokenPipeError: [Errno 32] Broken pipe
# often followed at exit by:
# Exception ignored in: <_io.TextIOWrapper ...>

The fix, in order

  1. Recognize the benign case and do nothing to the logic. If output is piped to head, less (quit early), or another consumer that closes early, the BrokenPipeError is the correct description of events. Pipelines are supposed to work this way; only the noise needs handling.
  2. Restore the default SIGPIPE behavior for Unix CLI tools: from signal import signal, SIGPIPE, SIG_DFL; signal(SIGPIPE, SIG_DFL) near startup. The process then dies quietly by the signal, like standard Unix tools, instead of printing a traceback.
  3. Or catch it at the top level and exit cleanly: wrap main() in a try/except BrokenPipeError that redirects the broken stream to devnull (os.dup2(os.open(os.devnull, os.O_WRONLY), sys.stdout.fileno())) so the interpreter's exit-time flush does not raise the “Exception ignored” follow-up.
  4. In servers and sockets, treat it as “client gone”. Catch it where you write responses; log at most at debug level, stop sending, and clean up the connection. A client disconnect is routine traffic, not an application bug, and should never page anyone.
  5. Check for double-close in your own plumbing. A stream closed by your code (an early close() in a finally, a context manager exiting) and then written by another part reproduces this without any external reader; there, it is a real bug in ordering, and the traceback's write site is the place to fix.

If it still happens

If writes fail with broken pipe immediately, even with a live reader, the reader process died for its own reasons (crash, killed, failed to start in a subprocess pipeline). Inspect the consumer: subprocess pipelines where the child's stderr was never drained are a recurring cause, since a full stderr buffer can kill or block the child while the parent keeps writing.

Common questions

Why is there a second error, 'Exception ignored', after the first? Because the interpreter flushes standard streams during shutdown, and the flush hits the same broken pipe, raising inside cleanup code where it can only be reported as ignored. Redirecting stdout to devnull in your handler (step three) silences it properly.

Does BrokenPipeError mean data was lost? It means the remaining data had nowhere to go: the reader had already stopped reading, by its own choice or death. What the reader consumed before closing arrived intact; everything after the close was never going to be read, which for head-style consumers is the intended behavior.

Related errors

ConnectionError · OSError · StopIteration