Skip to content

[FlightReply] Don't drop FormData entries in decodeReplyFromBusboy - #36468

Merged
unstubbable merged 6 commits into
react:mainfrom
unstubbable:fix-form-data-regression
May 14, 2026
Merged

[FlightReply] Don't drop FormData entries in decodeReplyFromBusboy#36468
unstubbable merged 6 commits into
react:mainfrom
unstubbable:fix-form-data-regression

Conversation

@unstubbable

@unstubbableunstubbable commented May 13, 2026

Copy link
Copy Markdown
Collaborator

Fixes a regression from #36425 where referenced FormData entries can be dropped by decodeReplyFromBusboy when files are interleaved with text fields in the payload.

decodeReplyFromBusboy queues text fields that arrive while a file is being streamed and flushes them after the last file's 'end', working around busboy emitting 'end' deferred relative to subsequent 'field' events. With multiple files interleaved with text, this loses the relative order of the affected text entries. The reorder was a long-standing but invisible issue — entries came back in the wrong order but were all present — until #36425 tightened how referenced FormData entries are collected from the backing store to rely on them being contiguous. With that assumption violated, referenced FormDatas can now come back with some entries dropped. The pattern is most easily surfaced through useActionState actions that return the submitted FormData as part of their state.

This replaces the tail-flush with a linked list of pending files. Text fields that arrive while a file is in flight are queued on the tail file's queuedFields; fields that arrive when the list is empty resolve immediately. flush() walks from the head, resolving each completed file followed by its queued fields, and stops at the first file that hasn't ended yet. The backing FormData now matches the payload's order, restoring the contiguity assumption (and fixing the long-standing reorder as a side effect). The same change is applied to all five copies in react-server-dom-{webpack,turbopack,parcel,esm,unbundled}. Two new tests cover the multi-file interleave.

fixesvercel/next.js#93822

@github-actionsgithub-actionsBot added the React Core Team Opened by a member of the React Core Team label May 13, 2026
@unstubbable
unstubbableforce-pushed the fix-form-data-regression branch from 350689b to d94bedcCompareMay 13, 2026 22:22
@react-sizebot

react-sizebot commented May 13, 2026

Copy link
Copy Markdown

Comparing: 8fc5763...77b34cc

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.js=6.84 kB6.84 kB+0.05%1.88 kB1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js=614.17 kB614.17 kB=108.52 kB108.52 kB
oss-experimental/react-dom/cjs/react-dom.production.js=6.84 kB6.84 kB=1.88 kB1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js=680.11 kB680.11 kB=119.48 kB119.48 kB
facebook-www/ReactDOM-prod.classic.js=700.53 kB700.53 kB=123.06 kB123.05 kB
facebook-www/ReactDOM-prod.modern.js=690.84 kB690.84 kB=121.44 kB121.44 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js+0.90%115.46 kB116.50 kB+0.99%23.35 kB23.58 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js+0.90%115.46 kB116.50 kB+0.99%23.35 kB23.58 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.production.js+0.89%117.26 kB118.30 kB+0.98%23.71 kB23.95 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.production.js+0.87%119.53 kB120.57 kB+0.94%23.93 kB24.16 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.production.js+0.87%119.53 kB120.57 kB+0.94%23.93 kB24.16 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.production.js+0.86%121.32 kB122.36 kB+0.91%24.30 kB24.52 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.production.js+0.83%125.40 kB126.44 kB+0.93%24.86 kB25.09 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.production.js+0.83%125.40 kB126.44 kB+0.93%24.86 kB25.09 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.js+0.82%126.44 kB127.48 kB+0.92%25.10 kB25.33 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.js+0.82%126.44 kB127.48 kB+0.92%25.10 kB25.33 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.production.js+0.82%126.46 kB127.50 kB+0.92%25.09 kB25.32 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.production.js+0.82%126.46 kB127.50 kB+0.92%25.09 kB25.32 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.production.js+0.82%127.19 kB128.23 kB+0.92%25.24 kB25.47 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.js+0.81%128.24 kB129.28 kB+0.90%25.47 kB25.70 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.production.js+0.81%128.25 kB129.29 kB+0.91%25.46 kB25.69 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js+0.51%236.07 kB237.28 kB+0.62%42.90 kB43.17 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js+0.51%236.07 kB237.28 kB+0.62%42.90 kB43.17 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js+0.51%238.16 kB239.37 kB+0.64%43.33 kB43.61 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.development.js+0.50%242.84 kB244.05 kB+0.73%43.51 kB43.82 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.development.js+0.50%242.84 kB244.05 kB+0.73%43.51 kB43.82 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.development.js+0.49%244.93 kB246.14 kB+0.70%43.95 kB44.25 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.development.js+0.49%249.36 kB250.57 kB+0.67%44.60 kB44.90 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.development.js+0.49%249.36 kB250.57 kB+0.67%44.60 kB44.90 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js+0.48%250.56 kB251.77 kB+0.66%44.92 kB45.21 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js+0.48%250.56 kB251.77 kB+0.66%44.92 kB45.21 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js+0.48%250.57 kB251.78 kB+0.66%44.92 kB45.22 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js+0.48%250.57 kB251.78 kB+0.66%44.92 kB45.22 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-server.node.development.js+0.48%251.45 kB252.66 kB+0.66%45.03 kB45.33 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js+0.48%252.65 kB253.86 kB+0.66%45.34 kB45.64 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js+0.48%252.66 kB253.87 kB+0.66%45.35 kB45.65 kB

Generated by 🚫 dangerJS against 77b34cc

@gnoffgnoff left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could store queueFields on the file entry. always push to the top pendingFile.

Then you only flush when you get data an end even on value and you flush each file followed by it's queueFields until you hit the next pending file. splice the files array to eliminate flushed files and fields

@unstubbable
unstubbableforce-pushed the fix-form-data-regression branch from d94bedc to 393e3aaCompareMay 13, 2026 23:26
Fixes a regression from react#36425 where referenced `FormData` entries can
be dropped by `decodeReplyFromBusboy` when files are interleaved with
text fields in the payload.
`decodeReplyFromBusboy` queues text fields that arrive while a file is
being streamed and flushes them after the last file's `'end'`, working
around busboy emitting `'end'` deferred relative to subsequent `'field'`
events. With multiple files interleaved with text, this loses the
relative order of the affected text entries. The reorder was a
long-standing but invisible issue — entries came back in the wrong order
but were all present — until react#36425 tightened how referenced FormData
entries are collected from the backing store to rely on them being
contiguous. With that assumption violated, referenced FormDatas can now
come back with some entries dropped. The pattern is most easily surfaced
through `useActionState` actions that return the submitted `FormData` as
part of their state.
This replaces the tail-flush with a positionally-tagged buffer drained
in arrival order. `flush()` walks from a monotonic index pointer,
resolving text immediately and files once their `'end'` has fired, and
holding later entries when the cursor lands on a still-streaming file.
The backing FormData now matches the payload's order, restoring the
contiguity assumption (and fixing the long-standing reorder as a side
effect). The same change is applied to all five copies in
`react-server-dom-{webpack,turbopack,parcel,esm,unbundled}`. Two new
tests cover the multi-file interleave.
fixesvercel/next.js#93822
@unstubbable
unstubbableforce-pushed the fix-form-data-regression branch from 76b9503 to 5978b45CompareMay 13, 2026 23:40
@unstubbable
unstubbable marked this pull request as ready for review May 14, 2026 00:13
@unstubbable
unstubbable requested a review from gnoffMay 14, 2026 00:13
@unstubbable
unstubbable requested a review from gnoffMay 14, 2026 15:59
Comment threadpackages/react-server-dom-esm/src/server/ReactFlightDOMServerNode.js Outdated
@unstubbable
unstubbable merged commit b91823e into react:mainMay 14, 2026
237 checks passed
@unstubbable
unstubbable deleted the fix-form-data-regression branch May 14, 2026 20:04
github-actionsBot pushed a commit to code/lib-react that referenced this pull request May 17, 2026
…eact#36468)
Fixes a regression from react#36425 where referenced `FormData` entries can
be dropped by `decodeReplyFromBusboy` when files are interleaved with
text fields in the payload.
`decodeReplyFromBusboy` queues text fields that arrive while a file is
being streamed and flushes them after the last file's `'end'`, working
around busboy emitting `'end'` deferred relative to subsequent `'field'`
events. With multiple files interleaved with text, this loses the
relative order of the affected text entries. The reorder was a
long-standing but invisible issue — entries came back in the wrong order
but were all present — until react#36425 tightened how referenced FormData
entries are collected from the backing store to rely on them being
contiguous. With that assumption violated, referenced FormDatas can now
come back with some entries dropped. The pattern is most easily surfaced
through `useActionState` actions that return the submitted `FormData` as
part of their state.
This replaces the tail-flush with a linked list of pending files. Text
fields that arrive while a file is in flight are queued on the tail
file's `queuedFields`; fields that arrive when the list is empty resolve
immediately. `flush()` walks from the head, resolving each completed
file followed by its queued fields, and stops at the first file that
hasn't ended yet. The backing FormData now matches the payload's order,
restoring the contiguity assumption (and fixing the long-standing
reorder as a side effect). The same change is applied to all five copies
in `react-server-dom-{webpack,turbopack,parcel,esm,unbundled}`. Two new
tests cover the multi-file interleave.
fixesvercel/next.js#93822
DiffTrain build for [b91823e](react@b91823e)
github-actionsBot pushed a commit to code/lib-react that referenced this pull request May 17, 2026
…eact#36468)
Fixes a regression from react#36425 where referenced `FormData` entries can
be dropped by `decodeReplyFromBusboy` when files are interleaved with
text fields in the payload.
`decodeReplyFromBusboy` queues text fields that arrive while a file is
being streamed and flushes them after the last file's `'end'`, working
around busboy emitting `'end'` deferred relative to subsequent `'field'`
events. With multiple files interleaved with text, this loses the
relative order of the affected text entries. The reorder was a
long-standing but invisible issue — entries came back in the wrong order
but were all present — until react#36425 tightened how referenced FormData
entries are collected from the backing store to rely on them being
contiguous. With that assumption violated, referenced FormDatas can now
come back with some entries dropped. The pattern is most easily surfaced
through `useActionState` actions that return the submitted `FormData` as
part of their state.
This replaces the tail-flush with a linked list of pending files. Text
fields that arrive while a file is in flight are queued on the tail
file's `queuedFields`; fields that arrive when the list is empty resolve
immediately. `flush()` walks from the head, resolving each completed
file followed by its queued fields, and stops at the first file that
hasn't ended yet. The backing FormData now matches the payload's order,
restoring the contiguity assumption (and fixing the long-standing
reorder as a side effect). The same change is applied to all five copies
in `react-server-dom-{webpack,turbopack,parcel,esm,unbundled}`. Two new
tests cover the multi-file interleave.
fixesvercel/next.js#93822
DiffTrain build for [b91823e](react@b91823e)
MaxwellCohen pushed a commit to MaxwellCohen/react that referenced this pull request May 26, 2026
…eact#36468)
Fixes a regression from react#36425 where referenced `FormData` entries can
be dropped by `decodeReplyFromBusboy` when files are interleaved with
text fields in the payload.
`decodeReplyFromBusboy` queues text fields that arrive while a file is
being streamed and flushes them after the last file's `'end'`, working
around busboy emitting `'end'` deferred relative to subsequent `'field'`
events. With multiple files interleaved with text, this loses the
relative order of the affected text entries. The reorder was a
long-standing but invisible issue — entries came back in the wrong order
but were all present — until react#36425 tightened how referenced FormData
entries are collected from the backing store to rely on them being
contiguous. With that assumption violated, referenced FormDatas can now
come back with some entries dropped. The pattern is most easily surfaced
through `useActionState` actions that return the submitted `FormData` as
part of their state.
This replaces the tail-flush with a linked list of pending files. Text
fields that arrive while a file is in flight are queued on the tail
file's `queuedFields`; fields that arrive when the list is empty resolve
immediately. `flush()` walks from the head, resolving each completed
file followed by its queued fields, and stops at the first file that
hasn't ended yet. The backing FormData now matches the payload's order,
restoring the contiguity assumption (and fixing the long-standing
reorder as a side effect). The same change is applied to all five copies
in `react-server-dom-{webpack,turbopack,parcel,esm,unbundled}`. Two new
tests cover the multi-file interleave.
fixesvercel/next.js#93822
MaxwellCohen pushed a commit to MaxwellCohen/react that referenced this pull request May 26, 2026
…eact#36468)
Fixes a regression from react#36425 where referenced `FormData` entries can
be dropped by `decodeReplyFromBusboy` when files are interleaved with
text fields in the payload.
`decodeReplyFromBusboy` queues text fields that arrive while a file is
being streamed and flushes them after the last file's `'end'`, working
around busboy emitting `'end'` deferred relative to subsequent `'field'`
events. With multiple files interleaved with text, this loses the
relative order of the affected text entries. The reorder was a
long-standing but invisible issue — entries came back in the wrong order
but were all present — until react#36425 tightened how referenced FormData
entries are collected from the backing store to rely on them being
contiguous. With that assumption violated, referenced FormDatas can now
come back with some entries dropped. The pattern is most easily surfaced
through `useActionState` actions that return the submitted `FormData` as
part of their state.
This replaces the tail-flush with a linked list of pending files. Text
fields that arrive while a file is in flight are queued on the tail
file's `queuedFields`; fields that arrive when the list is empty resolve
immediately. `flush()` walks from the head, resolving each completed
file followed by its queued fields, and stops at the first file that
hasn't ended yet. The backing FormData now matches the payload's order,
restoring the contiguity assumption (and fixing the long-standing
reorder as a side effect). The same change is applied to all five copies
in `react-server-dom-{webpack,turbopack,parcel,esm,unbundled}`. Two new
tests cover the multi-file interleave.
fixesvercel/next.js#93822
mohamedasem318 added a commit to mohamedasem318/Serenify that referenced this pull request Jul 27, 2026
…ange reaching P6/P7 (#176) (#180)
* chore(deps): bump next 16.2.6 -> 16.2.11 for nine security advisories
All nine advisories behind the 18 open Dependabot `next` alerts are fixed in
16.2.11, confirmed from the 16.2.11 release notes (which link all nine GHSAs)
and cross-checked against each advisory's own affected range. Four are High:
DoS in App Router Server Actions (GHSA-m99w-x7hq-7vfj), middleware/proxy bypass
with Turbopack + single locale (GHSA-6gpp-xcg3-4w24), SSRF in rewrites
(GHSA-p9j2-gv94-2wf4), SSRF in Server Actions on custom servers
(GHSA-89xv-2m56-2m9x).
Two of the nine are reachable in this app as configured: the Server Actions DoS
and the Server Function endpoint disclosure (GHSA-955p-x3mx-jcvp). The other
seven need config this app does not have -- no `i18n`, no rewrites, no custom
server, no edge runtime, no `images.remotePatterns`, and no `fetch(Request,
init)` mismatched-init call sites.
Bumped ahead of P6 deliberately. P6 reads the Next 16 routing guides out of
`node_modules/next/dist/docs/` (T079) and performs a root-route takeover (T086);
16.2.10 ships a docs backport (#94935) that corrects `03-layouts-and-pages.md`
and `02-project-structure.md` -- the two files that answer T079's mandated
question about `app/page.tsx` vs `app/(public)/page.tsx`. Bumping first means P6
is built and documented against what actually ships.
Nothing in 16.2.7-16.2.11 touches route groups or root `page.tsx` resolution,
and `next/image` sizing is unchanged, so P6/P7 are unaffected by the bump
itself. 16.2.8/16.2.9/16.2.10 carry no code at all (dist-tag repair x2, and
republishing @next/swc-wasm-web).
One behaviour change lands in P4's path and is favourable: 16.2.7 carries
`Don't drop FormData entries` (#94240, a sync of react/react#36468). 16.2.6
predates it, and `app/(auth)/signup/actions.ts` reads `terms_privacy_version`
off FormData, which `handle_new_user()` requires before it writes a consent row.
Refs #176.
Co-authored-by: Fatma-Alzahraaa <fatmaalzahraa.emad@gmail.com>
Co-authored-by: gehaddmohamedd <gehadmohamed2412@gmail.com>
Co-authored-by: hebatullah003 <hebatullahelgazoly@gmail.com>
* chore(deps): lock next 16.2.11 and its nine @next/* sub-packages
Regenerated by `npm install` from the manifest pin in the previous commit.
Nothing else was run -- no `npm update`, no `npm audit fix`.
Exactly ten packages move, and every one of them is next or a next-owned
sub-package: `next`, `@next/env`, and the eight `@next/swc-*` platform
binaries. Zero packages added, zero removed. No unrelated transitive dependency
was forced to move -- next@16.2.11 declares byte-identical dependencies and
peer ranges to 16.2.6, React's range included.
`postcss` deliberately does not move and is worth stating plainly, because it
is the reason this bump does not clear the whole alert list: next pins
`postcss: "8.4.31"` as a hard dependency at 16.2.11 exactly as it did at
16.2.6, so `node_modules/next/node_modules/postcss` stays at 8.4.31 and the
top-level copy stays at 8.5.14. Both open postcss advisories (which want 8.5.12
and 8.5.18) survive this change, as does sharp@0.34.5 (wants 0.35.0). 18 of the
21 open alerts clear; 3 remain.
Refs #176.
Co-authored-by: Fatma-Alzahraaa <fatmaalzahraa.emad@gmail.com>
Co-authored-by: gehaddmohamedd <gehadmohamed2412@gmail.com>
Co-authored-by: hebatullah003 <hebatullahelgazoly@gmail.com>
* docs(backlog): log the undocumented e2e service-role key (#179)
Found while recording the pre-bump Playwright baseline for #176: a clean
checkout cannot run the e2e suite at all. `globalSetup` dies immediately with
`Error: supabaseKey is required.` because `tests/e2e/setup/admin-client.ts:22`
builds its admin client from `SUPABASE_SERVICE_ROLE_KEY`, and nothing documents
that the key must be set. Cost one full aborted suite run before it was
diagnosed.
Logged rather than fixed, and the entry is explicit about why the obvious fix
is wrong: `.env.local.example` is the runtime env example, and the service-role
key is deliberately not part of the runtime surface. #142 removed the runtime
service-role path, and `tests/unit/runtime-secret-posture.test.ts` actively
guards that removal -- it fails if the literal token appears anywhere under
`app/` or `lib/`, and asserts `lib/supabase/admin.ts` does not exist. Adding
the key there would advertise a capability the codebase has deliberately
deleted and invite the exact regression that test exists to catch. It is e2e
test infrastructure and belongs in e2e setup documentation.
Filed 1:1 as issue #179 per Principle VIII. Not implemented here -- this PR
bumps `next` and nothing else, and where the documentation belongs is its own
decision.
Co-authored-by: Fatma-Alzahraaa <fatmaalzahraa.emad@gmail.com>
Co-authored-by: gehaddmohamedd <gehadmohamed2412@gmail.com>
Co-authored-by: hebatullah003 <hebatullahelgazoly@gmail.com>
* docs(013): record the P8 pre-deploy consent-row count prompted by the FormData fix
Note only -- no task's acceptance criteria are changed, and nothing runs now.
Next 16.2.6 carries a FormData-dropping bug, fixed in 16.2.7 by #94240 (a sync
of react/react#36468) and shipped here by the 16.2.6 -> 16.2.11 bump.
`app/(auth)/signup/actions.ts:33` reads `terms_privacy_version` off FormData,
and `handle_new_user()` writes a `user_consents` row only when the signup
metadata carries that key. A dropped entry is therefore a silently missing
consent row rather than an error, which is exactly the failure mode nobody
notices.
So before the P8 deploy, a READ-ONLY count on hosted of `auth.users` rows with
no `terms_privacy` consent row is worth recording. Explicitly a measurement:
FR-041 forbids backfill and T137 separately asserts `user_consents` is empty
post-migration, so a non-zero result is a finding to report, not something to
repair in P8.
Placed in the P8 phase preamble rather than folded into T135's or T137's
"Done when", so it does not quietly redefine what those tasks require.
Co-authored-by: Fatma-Alzahraaa <fatmaalzahraa.emad@gmail.com>
Co-authored-by: gehaddmohamedd <gehadmohamed2412@gmail.com>
Co-authored-by: hebatullah003 <hebatullahelgazoly@gmail.com>
---------
Co-authored-by: Fatma-Alzahraaa <fatmaalzahraa.emad@gmail.com>
Co-authored-by: gehaddmohamedd <gehadmohamed2412@gmail.com>
Co-authored-by: hebatullah003 <hebatullahelgazoly@gmail.com>
MaxwellCohen pushed a commit to MaxwellCohen/react that referenced this pull request Jul 27, 2026
…eact#36468)
Fixes a regression from react#36425 where referenced `FormData` entries can
be dropped by `decodeReplyFromBusboy` when files are interleaved with
text fields in the payload.
`decodeReplyFromBusboy` queues text fields that arrive while a file is
being streamed and flushes them after the last file's `'end'`, working
around busboy emitting `'end'` deferred relative to subsequent `'field'`
events. With multiple files interleaved with text, this loses the
relative order of the affected text entries. The reorder was a
long-standing but invisible issue — entries came back in the wrong order
but were all present — until react#36425 tightened how referenced FormData
entries are collected from the backing store to rely on them being
contiguous. With that assumption violated, referenced FormDatas can now
come back with some entries dropped. The pattern is most easily surfaced
through `useActionState` actions that return the submitted `FormData` as
part of their state.
This replaces the tail-flush with a linked list of pending files. Text
fields that arrive while a file is in flight are queued on the tail
file's `queuedFields`; fields that arrive when the list is empty resolve
immediately. `flush()` walks from the head, resolving each completed
file followed by its queued fields, and stops at the first file that
hasn't ended yet. The backing FormData now matches the payload's order,
restoring the contiguity assumption (and fixing the long-standing
reorder as a side effect). The same change is applied to all five copies
in `react-server-dom-{webpack,turbopack,parcel,esm,unbundled}`. Two new
tests cover the multi-file interleave.
fixesvercel/next.js#93822
SyMind pushed a commit to SyMind/react that referenced this pull request Aug 11, 2026
* [Flight] Restore standard React version placeholder
* [Flight Reply] Early bailout if backing entry for Blob deserialization is not a Blob (react#36055)
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
(cherry picked from commit 12ba7d8)
* [Flight] Avoid consuming cyclic models multiple times
Co-authored-by: "Sebastian \"Sebbie\" Silbermann" <sebastian.silbermann@vercel.com>
(cherry picked from commit 672b242)
* [FlightReply] Type hardening and performance improvements
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
(cherry picked from commit 795203e)
* [FlightReply] Don't drop FormData entries in `decodeReplyFromBusboy` (react#36468)
Fixes a regression from react#36425 where referenced `FormData` entries can
be dropped by `decodeReplyFromBusboy` when files are interleaved with
text fields in the payload.
`decodeReplyFromBusboy` queues text fields that arrive while a file is
being streamed and flushes them after the last file's `'end'`, working
around busboy emitting `'end'` deferred relative to subsequent `'field'`
events. With multiple files interleaved with text, this loses the
relative order of the affected text entries. The reorder was a
long-standing but invisible issue — entries came back in the wrong order
but were all present — until react#36425 tightened how referenced FormData
entries are collected from the backing store to rely on them being
contiguous. With that assumption violated, referenced FormDatas can now
come back with some entries dropped. The pattern is most easily surfaced
through `useActionState` actions that return the submitted `FormData` as
part of their state.
This replaces the tail-flush with a linked list of pending files. Text
fields that arrive while a file is in flight are queued on the tail
file's `queuedFields`; fields that arrive when the list is empty resolve
immediately. `flush()` walks from the head, resolving each completed
file followed by its queued fields, and stops at the first file that
hasn't ended yet. The backing FormData now matches the payload's order,
restoring the contiguity assumption (and fixing the long-standing
reorder as a side effect). The same change is applied to all five copies
in `react-server-dom-{webpack,turbopack,parcel,esm,unbundled}`. Two new
tests cover the multi-file interleave.
fixesvercel/next.js#93822
(cherry picked from commit b91823e)
* [FlightReply] Performance improvements when decoding (react#37087)
This fixes security vulnerabilities in Server Functions.
(cherry picked from commit 1dd4ecb)
* [Flight Reply] Align Rspack decoders with upstream changes
Mirror the selected Reply changes into the Rspack-owned browser, edge, and Node adapters after the dependency-closed upstream backports.
Forward caller-provided array size limits, preserve multipart field/file order, and settle failed async iterators without recursive error re-entry. Add public behavior coverage across every Rspack decoder, action-selection path, cyclic collection type, iterator settlement, and Busboy ordering direction.
This is a tactical source-parity change for the existing proposal branch; it does not make that branch current with React main.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <sebastian.silbermann@vercel.com>
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

useActionState with form containing file input receives missmatched FormData

4 participants

@unstubbable@react-sizebot@gnoff@das810835-ux