Bun 1.4.3 fetch Content-Length check: send a Sume JSON body as bytes

Bun 1.4.3 rejects fetch when a declared Content-Length mismatches a stream body. For a Sume submit, skip the header and pass the encoded JSON.

4 min readSume
All posts

Do not set Content-Length by hand on a Sume submit. Pass the JSON as a string or as TextEncoder bytes and let fetch compute the length. Bun v1.4.3 now rejects a fetch whose declared Content-Length does not match a ReadableStream body, so a stream body with a wrong hand-written header is no longer silently sent.

Why a hand-written length goes wrong

The Bun v1.4.3 release notes (read 2026-10-10) list this under fetch: fetch() rejects when your code passes a Content-Length header that does not match the ReadableStream body it sends. The note is about stream bodies, so a string or bytes body is not what it targets. The usual way to get a wrong length is counting characters instead of bytes. A prompt in Korean or with an emoji is longer in UTF-8 than String.length says.

const payload = {
  model: "seedance-2.5",
  prompt: "비 오는 서울 골목, 네온 간판 🌧️",
  duration: 5,
};
const text = JSON.stringify(payload);
const bytes = new TextEncoder().encode(text);
console.log(text.length, bytes.length); // 70 96

In that example the string is 70 UTF-16 units but 96 bytes on the wire. A header built from text.length would under-declare by 26 bytes.

The submit that needs no header

The video docs show POST /v1/videos with model and prompt, and list duration as an optional integer. seedance-2.5 accepts 4 to 30 seconds per the same page. Sume wants Content-Type: application/json; the errors page lists 415 unsupported_media_type for anything else. Sending a string or a Uint8Array lets the runtime set the length.

const res = await fetch("https://api.sume.com/v1/videos", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUME_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "promo-0042-v1",
  },
  body: bytes, // no Content-Length header
});
const job = await res.json();
console.log(res.status, job.id, job.polling_url);

Rules of thumb

A submit body is small, so there is no reason to stream it. Compute the bytes once, reuse them across retries, and let the runtime own the framing. The checklist below is what to review in a client that talks to Sume from Bun.

  • Never copy Content-Length from another request or a proxy into a Sume call.
  • Do not stream a JSON body unless you must; a typical submit is a few hundred bytes, so a stream buys nothing and adds the mismatch failure mode.
  • Keep the Idempotency-Key stable across retries of the same submit, so a failed length check cannot turn into two paid jobs.
  • If a body is too large, Sume answers 413 payload_too_large; that is a size limit, not a length mismatch.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume