Stream API - Error Handling
Streams fail in several ways: the network drops, the server sends an error mid-body, a transform throws, or the consumer cancels. Robust handling covers all four and releases resources.
Try, catch, and finally
const reader = response.body.getReader();
try {
while (true) {
const { value, done } = await reader.read();
if (done) break;
process(value);
}
} catch (error) {
console.error('Stream failed', error);
} finally {
reader.releaseLock();
}
Propagation through pipes
await source
.pipeThrough(transform)
.pipeTo(destination)
.catch((error) => {
if (error.name === 'AbortError') return;
reportFailure(error);
});
An error in any stage aborts the whole pipeline by default. Errors thrown inside a transform reject the pipe promise.
Rejecting a stream deliberately
new ReadableStream({
start(controller) {
controller.error(new Error('Upstream unavailable'));
}
});
Distinguishing cancellation from failure
try {
await response.body.pipeTo(sink);
} catch (error) {
if (error.name === 'AbortError') {
status.textContent = 'Cancelled';
} else {
status.textContent = 'Failed';
}
}
User-initiated cancellation should not be reported as an error. Check the error name before displaying a message.
Partial results
When a stream fails after some chunks have been consumed, decide whether the partial data is useful. For a log viewer, keep what arrived and mark it incomplete. For a file download, discard the partial result to avoid corruption.
const chunks = [];
try {
for await (const chunk of response.body) {
chunks.push(chunk);
}
save(new Blob(chunks));
} catch (error) {
chunks.length = 0;
showRetry();
}
Timeouts
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 30000);
try {
await fetch(url, { signal: controller.signal });
} finally {
clearTimeout(timer);
}
Checklist
- Always release readers and writers.
- Treat
AbortErroras cancellation, not failure. - Validate the response status before streaming the body.
- Avoid unbounded buffering when fallback parsing is used.
- Log enough context to diagnose where a pipeline broke.