Bun 1.4.3 fetch stream errors: catch a cut-off Sume video download

Bun 1.4.3 fixes response streams that ended cleanly after a transfer failure. Still check the byte count when you save a finished Sume video to disk.

4 min readSume
All posts

Bun 1.4.3 (October 10, 2026) fixes cases where a fetch response stream ended cleanly after the transfer had actually failed. If you save a finished Sume video with Bun.write(path, response), upgrade, then add one more check anyway: compare the bytes you wrote with the Content-Length header when the server sent one, and re-download on a mismatch.

The fix is listed in the Bun v1.4.3 release notes (read 2026-10-13) next to related items: native readers now receive signal.reason instead of a generic AbortError when a body is aborted, and a cloned response body rejects on stream failure instead of just ending. The job and result side is covered in Jobs and results.

What Bun fixed

Before 1.4.3, a consumer reading the stream could see a normal end of data when the connection broke mid-body. For a small JSON reply that is a parse error you notice. For a multi-megabyte clip it is a file that plays for a few seconds and stops.

Bun 1.4.3 response-body items (Bun release notes, read 2026-10-13)
Release-note itemEffect on a download script
Stream ended cleanly instead of rejecting after a transfer failureA broken transfer now rejects; your catch runs
Aborted body gave a generic AbortErrorYou now get signal.reason, such as a TimeoutError
Cloned response body ended instead of rejectingtee-style reads also fail loudly

Why a size check still belongs in the script

A fixed runtime narrows the gap, not every gap: a proxy or CDN can close a response early with a status you cannot tell from success, and servers that stream without a length give you nothing to compare. A size check costs one stat call.

Separate that from the job itself. A finished Sume job is durable, so a bad download is never a reason to resubmit generation. Per Jobs and results, store the job id and read the result again; resubmitting would start a new billed job.

Save, verify, retry the read

This helper takes a URL you already read from a completed job's result, writes it, and retries only the download.

async function save(url: string, path: string) {
  for (let attempt = 0; attempt < 3; attempt++) {
    try {
      const res = await fetch(url, { signal: AbortSignal.timeout(120_000) });
      if (!res.ok) throw new Error(`download ${res.status}`);
      const expected = Number(res.headers.get("content-length") ?? NaN);
      const written = await Bun.write(path, res);
      if (!Number.isNaN(expected) && written !== expected) {
        throw new Error(`short file: ${written} of ${expected}`);
      }
      return written;
    } catch (err) {
      if (attempt === 2) throw err;
      await Bun.sleep(2 ** attempt * 1000);
    }
  }
}

Checklist

Keep generation and download as separate steps, so each has its own retry rule.

  • Retry the download, not the Sume submit.
  • Reread the result from the job id if the link no longer works.
  • Log err.cause or the abort reason; 1.4.3 now carries it through.
  • Delete the partial file before the next attempt.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume