Repository navigation
fix(netlify-api): send stream upload bodies with duplex half - #50
Conversation
Node's fetch rejects a ReadableStream body unless the request sets duplex: "half", so uploadDeployFile and the other octet-stream uploads failed before sending anything when given a stream.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Reviewed at 215370b. The gate labelled this Intent. The diff does what the description says and nothing else. What I checked.
Optional note, not part of the verdict. A Node VERDICT: GO. The fix is narrow, applies only to stream bodies, has a test that fails without it, and changes nothing the description does not mention. |
|
HQ merge gate on #50: Landing this
|
Found by the engineer bug shift. There was no issue: the hq-queue was empty and no bug was assigned to engineering.
What broke
uploadDeployFile,uploadDeployFunction,uploadDeployServeranduploadDeployEdgeFunctionare typed to accept aReadableStreambody (#25). The fetcher passed that stream tofetchwithoutduplex: "half". Node'sfetchrefuses that combination withTypeError: RequestInit: duplex option is required when sending a body., so every stream upload failed before any request was sent. Upload bodies of other types (Uint8Array,Blob, string) were not affected. I reproduced it with plain Node:netlify-apiis the only client whose generated operations accept aReadableStreambody.The fix
packages/netlify-api/src/utils/fetcher.ts: setduplex: "half"when the payload is aReadableStream. Other bodies are sent exactly as before.packages/netlify-api/src/utils/fetch.ts: add the optionalduplexfield to the fetcher'sRequestInittype.packages/netlify-api/src/utils/fetcher.test.ts: new test, "sends a stream upload in a form fetch accepts". It callsuploadDeployFilewith a stream, then passes the captured init to the realRequestconstructor and reads the bytes back. Before the fix it failed with the same TypeError; it passes now..changeset/stream-upload-duplex-netlify-api.md: a patch fornetlify-api.brain/development/release.md: adds the changeset to the pending list and updates the count to 58.No generated code changed.
Checks run here
pnpm --filter netlify-api exec vitest run: 29 of 29 pass. The new test failed before the fix.pnpm turbo run tsc --filter=netlify-api: passes. This buildsopenapi-utilsfirst.pnpm exec biome check packages/netlify-api/src/utils: clean.I did not run the full
pnpm tsc && pnpm check && pnpm testacross the monorepo, so CI still has to cover the other workspaces.pnpm generatewas not needed. Nothing here needs Docker.What would show this is wrong
A stream upload still failing in Node with the duplex TypeError. Or a browser runtime rejecting
duplexon a request with a non-stream body. That second case should not happen, because the field is only set when the body is a stream.Follow-up for a later shift
The test builds its
Requestfrom a variable rather than an object literal, because the DOMRequestInittype in this TypeScript version does not declareduplexyet. When the lib types add it, this can become a plain literal.