tezvyn:

How do you handle errors across piped streams safely?

AI-drafted, machine-checkedSource: interviewadvanced
WHAT IT TESTS

stream lifecycle and error propagation understanding.

OUTLINE

pipe connects streams but errors don't auto-propagate, must listen on each stream. Use pipeline() helper for auto-cleanup.

WHY PIPE ALONE ISN'T ENOUGH

The pipe() method connects readable output to writable input but does not create error propagation. If a transform stream fails halfway through a chain, the error event fires only on that stream. The source and destination streams remain open, holding file descriptors and memory. A listener only on the final stream will never hear the error from the middle stream, causing silent resource leaks.

THE PIPELINE() SOLUTION

Node.js provides stream.pipeline() to orchestrate safe chaining. It automatically attaches error listeners to every stream in the chain and ensures that any error triggers cleanup: aborting sources, destroying sinks, and closing all intermediate streams. This is the modern way. The old way required manually attaching error handlers to each stream, which was error-prone.

MANUAL ERROR HANDLING PATTERN

If using pipe() directly, listen to 'error' on every stream in the chain, not just the final one. Errors on the source, transforms, and destination must all be caught. On error, manually call destroy() on all streams to close file handles immediately. Forward the error to a central handler or callback so cleanup logic is not repeated.

COMPRESSION PIPELINE EXAMPLE

Reading a file, compressing it, and writing to a destination requires three streams. If the destination disk fills during write, the write stream emits error. Without a listener on the write stream, that error never surfaces. Meanwhile, the file read keeps consuming memory. The correct pattern either wraps with pipeline() or attaches error handlers to all three.

WHEN TO USE EACH APPROACH

pipeline() is recommended for all modern code; it's concise and guarantees correct cleanup. Use manual error handling only when pipeline() is unavailable or when custom cleanup logic is required beyond simple destruction. Always test failure scenarios by injecting errors into the middle of a chain to confirm no leaks occur.

Read the original → nodejs.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.