Next.js 16 File Uploads Broken by Proxy Handle


Last week, we upgraded our project from Next.js v15.15 to the new version v16.0. After the upgrade, we started experiencing issues with file uploads. I debugged the problem using an empty project to isolate the cause and discovered that there is a bug in the new proxy handler.
How to reproduce it?
Create Next.js app:
npx create-next-app@latest nextjs-form-reset
And create / update these 4 files:
app/state.ts
export interface State {}
app/action.ts
"use server";
import { State } from "./state";
export async function action(state: State, formData: FormData): Promise<State> {
console.log("Action called with: ", formData);
return state;
}
app/page.tsx
"use client";
import { useActionState } from "react";
import { State } from "./state";
import { action } from "./action";
export default function () {
const [state, formAction, isPending] = useActionState<State, FormData>(action, {});
return (
<form action={formAction} method="POST" encType="multipart/form-data">
<div>
<input type="file" name="file" />
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
);
}
next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
experimental: {
proxyClientMaxBodySize: '20mb',
serverActions: {
bodySizeLimit: '20mb',
},
},
};
export default nextConfig;
When you run the app and submit the form with a larger file (I’m using a 10MB image), you will see the following correct output in the next console:
Action called with: FormData {
'$ACTION_REF_1': '',
'$ACTION_1:0': '{"id":"60d9aa708d193f64ed39d6103bacccd511e5f972c2","bound":"$@1"}',
'$ACTION_1:1': '[{}]',
'$ACTION_KEY': 'kfc8fdef6421490deff683859af2a2eff',
file: File {
size: 12583050,
type: 'image/bmp',
name: 'empty_10mb.bmp',
lastModified: 1763298853354
}
}
Now when you create proxy.ts file in root folder, and add the following code:
export default async function proxy(req: Request) {}
and run the app again, you’ll see the following in the next console:
Action called with: FormData {}
- It seems the form data is somehow missing.
I’m not sure why this is happening, but I am sure it is not related to upload limit, or Next.js configuration. I’m guessing it’s related to the new proxy handler - for me it seems like a race condition.
Workaround
Since we cannot remove the proxy handler, we need a workaround. I found a solution that works for me, although it’s not ideal: awaiting the proxy execution until the POST body is fully loaded.
I added this ugly snippet to proxy handler:
try {
if (req.method === "POST") {
await req.formData();
}
} catch (error) {
...
}
I am going to try to find a better solution, but for now this is the best workaround I found.