Skip to content

fix: raise Next.js proxy body buffer so large uploads work - #846

Open
BrianBoyCN wants to merge 1 commit into
agegr:mainfrom
BrianBoyCN:fix/max-body-size-env
Open

BrianBoyCN wants to merge 1 commit into
agegr:mainfrom
BrianBoyCN:fix/max-body-size-env

Conversation

@BrianBoyCN

Copy link
Copy Markdown

Problem

Uploading a file larger than 10 MB through the Pi Web file panel fails with HTTP 500:

{"error":"Failed to parse body as FormData."}

Smaller uploads work. The failure is deterministic at exactly the 10 MB boundary, and it is not a proxy problem — it reproduces on 127.0.0.1:3000 with no reverse proxy in the path.

Root cause

Pi Web registers proxy.ts with matcher: ["/", "/login", "/api/:path*"], so every API request passes through the Next.js proxy/middleware layer. When a proxy is present, Next.js clones and buffers the request body and caps that buffer at 10 MB by default (experimental.proxyClientMaxBodySize).

Once the body exceeds the cap, Next only forwards the first 10 MB. The upload route's parseFormDataWithinLimit() then rebuilds a Response from the truncated bytes, and undici's multipart parser throws Failed to parse body as FormData. — which the route surfaces as a 500.

The server log shows the real reason:

Request body exceeded 10MB for /api/files/.../route?type=upload&conflict=error.
Only the first 10MB will be available unless configured.

The upload route advertises a 25 MB per-file / 100 MB per-request limit with dedicated 413 responses, but requests never reach that logic — the proxy layer truncates them first.

Fix

Set experimental.proxyClientMaxBodySize above the route's own 100 MB cap, configurable via a new PI_WEB_MAX_BODY_SIZE environment variable (default 128mb):

// next.config.ts
experimental: {
  proxyClientMaxBodySize: resolveMaxBodySize(),
},
  • bin/max-body-size.mjs parses b/kb/mb/gb suffixes or a raw byte count, falling back to 128mb for blank/invalid input.
  • The value is read when next.config.ts loads, so it can be changed without rebuilding (verified below).
  • README env tables updated in all four languages, and pi-web --help lists the new variable.

Verification

Built the app, then against the production server:

Upload Before After
5 MB 200 200
20 MB 500 Failed to parse body as FormData. 200
26 MB 500 413 Each upload must be 25MB or smaller (route's own limit)

Runtime override confirmed by starting the built server with PI_WEB_MAX_BODY_SIZE=1mb: a 5 MB upload then fails with the 1 MB buffering warning, proving the env var takes effect without a rebuild.

npm test (1024 passing), npx tsc --noEmit, and npm run lint are all green. New unit tests cover size parsing/fallback and assert the config stays above the 100 MB upload cap.

Fixes the missing 10 MB buffering configuration introduced when proxy.ts was added.

Next.js buffers the request body whenever a proxy/middleware is present and caps that buffer at 10 MB by default. Pi Web's upload route accepts up to 100 MB per request, so any upload over 10 MB was silently truncated by the proxy layer and failed with 'Failed to parse body as FormData.' (500) instead of succeeding or returning the intended 413.

Set experimental.proxyClientMaxBodySize from a new PI_WEB_MAX_BODY_SIZE env var (default 128mb). The value is read at config load, so it can be changed without rebuilding. Accepts b/kb/mb/gb suffixes or a raw byte count; invalid values fall back to the default.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant