gotchatypescriptnextjsMajor
Next.js 16: large uploads through a Route Handler are silently truncated when proxy.ts (middleware) matches the route
Viewed 0 times
Next.js 16.4
proxyClientMaxBodySizemiddlewareClientMaxBodySizerequest.body truncatedroute handler uploadgetCloneableBody
Error Messages
Problem
A Route Handler that streams a large upload from request.body (hundreds of MB) receives only the first N MB when the app has a proxy.ts (formerly middleware.ts) whose matcher includes that route. Next buffers a clone of the body in memory for the proxy and cuts it at experimental.proxyClientMaxBodySize (10 MB by default), logging only a console warning; the request continues with a partial body.
Solution
Exclude the upload route from the proxy matcher (e.g. add the path to the negative lookahead of config.matcher in proxy.ts) and check the session inside the route itself (return 401 JSON instead of redirecting). When the proxy does not run, Next never calls cloneBodyStream, so request.body streams straight from the socket with no buffering. Do not just raise proxyClientMaxBodySize: the whole body would then be held in memory. To get an upload progress bar with fetch (which has no upload progress events), send the file in fixed-size slices (Blob.slice) as successive requests and append them server-side.
Why
next/dist/server/lib/router-utils/resolve-routes.js wraps every request with getCloneableBody(req, proxyClientMaxBodySize); when the proxy matches, next-server.js calls cloneBodyStream() and finalize(), which replaces the request stream with the buffered copy that stops at the limit (body-streams.js: 'Only the first X will be available unless configured').
Code Snippets
proxy.ts matcher excluding the streaming upload route
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico|uploads/stream$|.*\\.(?:svg|png|jpg)$).*)"],
};Revisions (0)
No revisions yet.