Skip to content
Latchkey

Node.js "ERR_STREAM_PREMATURE_CLOSE" - Fix Stream Closed Early

A readable or writable stream was destroyed before it reached its natural end. pipeline() and finished() surface this as ERR_STREAM_PREMATURE_CLOSE - commonly from an aborted HTTP request or a peer that dropped the connection.

What this error means

A download, upload, or stream.pipeline() rejects with ERR_STREAM_PREMATURE_CLOSE. In CI it can be intermittent - the same job passes on retry - when the cause is a flaky connection rather than a logic bug.

Node output
Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close
    at IncomingMessage.onclose (node:internal/streams/end-of-stream:154:30)
    at IncomingMessage.emit (node:events:519:28)
  code: 'ERR_STREAM_PREMATURE_CLOSE'

Common causes

The connection dropped mid-stream

A network blip, an aborted request, or a server that closed the socket early ends the stream before completion. When transient, it passes on retry.

A stream destroyed without finishing

Code that calls destroy() (or returns early) on one end of a pipeline before the data has flushed triggers a premature close on the other end.

How to fix it

Use pipeline and retry transient closes

Prefer stream.pipeline() so cleanup is handled, and retry the operation when the close is caused by a flaky connection.

app.mjs
import { pipeline } from 'node:stream/promises';
async function download() {
  for (let attempt = 1; attempt <= 3; attempt++) {
    try { return await pipeline(source(), dest()); }
    catch (err) {
      if (err.code !== 'ERR_STREAM_PREMATURE_CLOSE' || attempt === 3) throw err;
    }
  }
}

Stop destroying the stream early

  1. Check for an early return or destroy() that abandons a stream before it finishes.
  2. Honour AbortSignal cleanly rather than tearing the socket down mid-write.
  3. Wait for the finish/close event before treating the transfer as done.

How to prevent it

  • Use stream.pipeline() so partial failures clean up consistently.
  • Retry premature-close failures that stem from transient network drops.
  • Avoid destroying a stream until its peer has flushed.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →