Repository navigation
Conversation
The `new Response(S3File)` section of the S3 page says that the response is a redirect. It does not say what a read or a write of that response gives. The section now says that the response has no body, that `Bun.write()` and `S3File.write()` write an empty file from it, and what to pass instead: the `S3File` to copy the file, or `s3file.stream()` for a response that carries its bytes.
|
Updated 5:15 AM PT - Oct 25th, 2026
✅ @robobun, your commit d72fa05eb8c91a61e5a9ee05f09900839ca54953 passed in 🧪 To try this PR locally: bunx bun-pr 46874That installs a local version of the PR into your bun-46874 --bun |
StatusReproduced on 1.4.3-canary.1 and on a debug build of main (179664e). Run this from the repo root. It uses the S3 server in import { S3Client } from "bun";
import { serve } from "./test/packages/s3-server/index.ts";
const server = serve({ buckets: ["bucket"] });
const client = new S3Client(server.clientOptions("bucket"));
await client.write("from", "hello world");
const size = key => server.buckets.get("bucket").current(key)?.data.size;
console.log(await client.file("a").write(new Response(client.file("from"))), size("a")); // 0 0
console.log(await client.file("d").write(client.file("from")), size("d")); // 11 11
server.stop(true);
PR: #46874 |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Document response body behavior docs/runtime/s3.mdx |
The documentation states that a response constructed from an S3File has an empty body. It shows copying the file directly and creating a response with s3file.stream(). |
Possibly related PRs
- oven-sh/bun#38364: Addresses empty FormData parts for S3-backed entries and recommends materializing the bytes.
- oven-sh/bun#42786: Addresses empty stdin when an S3-backed
Responseis used as shell input. - oven-sh/bun#46673: Defines behavior for APIs that consume bytes from an S3-backed Blob.
Suggested reviewers: alii
Priority:
Merge Risk: 
Minimal · up to d72fa
-
No actionable merge-blocking risk remains.
Pre-merge checks: 
4
-
Full details: Title check
-
Explanation
The title "docs: say that
new Response(S3File)has no body" is a short, specific, single-sentence summary of the main change. The PR updates docs/runtime/s3.mdx to state that the redirect response from new Response(S3File) has no body, which the title captures directly. It is a conventional docs: prefix title and does not contain file lists, emojis, or vague terms.
Full details: Description check
-
Explanation
The description follows the template's two sections. 'How did you verify your code works?' is answered in the Fix section, which says each new sentence and the example were run against the S3 server in test/packages/s3-server on 1.4.3-canary.1 and a debug build of main. The full script and output are in Notes. 'What does this PR do?' is covered by the Problem and Fix sections, which explain the missing documentation and the added copy example. The description also gives background on the cause and scope, so it is complete for a docs-only change.
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
Problem
docs/runtime/s3.mdxsays thatnew Response(s3file)is a redirect. It does not say that the response has no body.await dest.write(new Response(s3file))andawait Bun.write(path, new Response(s3file))read like a copy. Each one resolves with0and leaves an empty destination, also when the destination had content. The page has no example of a copy.Fix
new Response(S3File)section now says that the response has no body, whatresponse.text()and a write of the response give, and what to pass instead.write(s3file)to copy the file, andnew Response(s3file.stream())for a response that carries its bytes.test/packages/s3-server, on 1.4.3-canary.1 and on a debug build of main (179664e). The script and its output are in Notes.Background
new Response(s3file)is a 302 with a presigned URL inLocation.Bun.servesends it so that the server does not download the file (feat(s3) s3 client #15740). Its body is null (Keep body stream bookkeeping independent of the body's source #42116).Bun.write()andS3File.write()write the body of theResponsethey get. A null body gives an empty file, as forResponse.redirect(url).write()that rejects this response, or that reads the S3 file, was weighed and left out. The same question applies to every consumer of the body (text(),.body,Bun.spawnstdin), and the answer is a decision for a maintainer.Notes
Where this comes from. No user reported it. A test run of another S3 change found that
write(new Response(s3file))stores an empty object. A check of the history showed that the empty body is deliberate, so the docs are the place that was missing it.The script. Run it from the repo root. It needs no network.
The output. It is the same on 1.4.3-canary.1+367d939d9 and on a debug build of main (179664e).
The request log shows the cause of the empty destination. The two writes of the redirect response send a
PutObjectfora.jsonandb.jsonand noGetObjectfor123.json.Why the body is empty. The S3 branch of the
Responseconstructor (src/runtime/webcore/Response.rs:1018) signs a GET URL, sets status 302 andLocation, and stores a null body. It keeps no reference to theS3File. #15740 shipped it with an empty body, and #42116 made that body null, as forResponse.redirect().write_file_internal(src/runtime/webcore/Blob.rs:4567) then handles the response likenew Response(null).Other forms, for comparison.
write(s3file),write(new Response(s3file.stream()))andwrite(new Request(url, { method: "POST", body: s3file }))store all the bytes. ARequestkeeps theS3Fileas its body. Only theResponseconstructor makes a redirect from it.Not in this PR.
S3Fileinstances work withfetch(),Response, and other web APIs that acceptBlobinstances" on the same page stays as it is. Refuse an S3-backed Blob at spawn stdin, in the shell, inBun.buildfiles and in redis #46673 adds a paragraph next to it.no test proof · iteration 0 · docs-only change; test-proof not applicable