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.

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 96In 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-Lengthfrom 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-Keystable 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
- bun run --check: type errors stop before a Sume job submits
Bun 1.4.3 adds bun check and a --check flag on bun run. Use it so a type error in your Sume script fails before a paid generation request is sent.
- Can you cancel an image generation on Sume? Only before it starts
Cancelling a Sume image job works only before generation work starts. After that the API returns 409 job_generation_already_started and the job runs and bills.
- Know the day Sume lists a new video model: a catalog check script
Vendors launch video models weekly. A short Python script reads GET /v1/videos/models and flags when an id or name appears, with exit codes for cron or CI.
- A circuit breaker for paid video API calls: cap, poll, cancel
Guard paid video generation with three layers: a per-run spend cap, a loop breaker in your code, and cancel. Sume charges for work done before a cancel.
Written by Sume