HTTP 413 is Content Too Large: the request body is larger than the server is willing or able to process (RFC 9110 section 15.5.14). RFC 9110 gave it that name; RFC 7231 called it Payload Too Large and RFC 2616 Request Entity Too Large, the phrase nginx still prints and Go’s http.StatusRequestEntityTooLarge still carries. The server may close the connection rather than read the rest, and should send Retry-After if the limit is only temporary.
Find the limit that fired
Every layer an upload passes through has its own:
Cloudflare 100 MB on Free and Pro, 200 MB Business, 500 MB Enterprise 413
nginx client_max_body_size, default 1m 413
ingress-nginx nginx.ingress.kubernetes.io/proxy-body-size 413
Apache httpd LimitRequestBody, default 1 GiB since 2.4.54 413
Express express.json() limit, default '100kb' 413
Flask MAX_CONTENT_LENGTH 413
Django DATA_UPLOAD_MAX_MEMORY_SIZE, default 2.5 MB 400
Raise the outermost limit first: nginx’s 1 MB default stops an upload before your app’s 50 MB setting ever matters. Django is the odd one out. Its limit raises RequestDataTooBig, a SuspiciousOperation, which Django answers with 400, not 413, and it doesn’t count file uploads when you read request.POST.
“Connection reset” instead of a 413
nginx’s documentation warns that browsers cannot correctly display this error. The server answers while the browser is still sending, then closes the connection, and the browser reports a failed upload instead of showing the 413. Check file.size in the page before uploading, and have API clients send Expect: 100-continue, which gives the server the chance to answer 413 before the body leaves the client.
413 or another code
this body is over the per-request limit 413 Content Too Large
the server, or the user's quota, is out of room 507 Insufficient Storage
the headers are too big 431 Request Header Fields Too Large
the URL is too long 414 URI Too Long
the server needs to know the size first 411 Length Required
413 isn’t heuristically cacheable.
In your stack
location /uploads/ {
client_max_body_size 50m;
}
app.use(express.json({ limit: '1mb' })); // Express: past 1 MB, 413 with type 'entity.too.large'
app.config["MAX_CONTENT_LENGTH"] = 16 * 1024 * 1024 # Flask: 413 past 16 MB
r.Body = http.MaxBytesReader(w, r.Body, 10<<20)
if err := json.NewDecoder(r.Body).Decode(&v); err != nil {
var tooBig *http.MaxBytesError
if errors.As(err, &tooBig) {
http.Error(w, "body over 10 MB", http.StatusRequestEntityTooLarge)
return
}
http.Error(w, "bad JSON", http.StatusBadRequest)
return
}
Go’s MaxBytesReader stops reading at the limit and asks the server to close the connection afterwards, but it doesn’t send the 413 for you.
Search payload too large in the tool below: it finds 413 by its old name.