NGINX 413: REQUEST ENTITY TOO LARGE ON UPLOAD ------------------------------------------------------------------------ nginx refused the request body because it exceeded client_max_body_size, which defaults to just 1 MB. The trap is that several layers can each impose their own limit, and raising it in the application changes nothing when the proxy in front rejects the body first. CONFIDENCE : medium VERIFIED : 2026-08-08 (fresh, 0d old) URL : https://knowbase.sh/k/nginx-413-request-entity-too-large ERROR ------------------------------------------------------------------------ 413 Request Entity Too Large CODES: 413 PROBLEM ------------------------------------------------------------------------ File uploads fail above a certain size while smaller ones succeed. The application never sees the request, so its own logs are silent and its upload limit appears to be ignored. Raising the framework's limit has no effect, which makes the boundary look arbitrary — it is nginx rejecting the body before anything downstream is involved. ROOT CAUSE ------------------------------------------------------------------------ 1. [primary] client_max_body_size is at its default of 1 MB nginx caps request bodies at one megabyte unless told otherwise. Most people never set the directive, so the first upload over that size fails on a stock configuration. how to tell: The nginx error log records 'client intended to send too large body' with the exact byte count, and the boundary sits at 1048576 bytes 2. [primary] The directive is set in the wrong context client_max_body_size applies in http, server and location blocks, and the most specific match wins. A generous value in http is overridden by a stale small one in the location that actually handles uploads. how to tell: nginx -T shows the directive more than once, with a smaller value in the block matching the upload path 3. [common] Another proxy layer in front imposes its own limit A CDN, load balancer or ingress controller rejects the body before nginx sees it. The response looks identical, so fixing nginx changes nothing. how to tell: curl against the origin accepts the upload while the same request to the public hostname fails, and nginx's own error log has no matching entry 4. [common] The Kubernetes ingress annotation is missing An ingress-nginx controller generates its configuration from annotations, so editing nginx.conf inside the pod is overwritten. The limit has to be declared on the Ingress object. how to tell: The rejection comes from an ingress-nginx pod and no proxy-body-size annotation is present on the Ingress 5. [edge] The application also has a limit, reached after nginx is fixed Raising nginx's limit moves the failure downstream rather than removing it. The framework then rejects the body with its own error, which is easy to mistake for the fix not working. how to tell: The status code changes from 413 to a framework-specific error, or the message now names the application rather than nginx SOLUTION ------------------------------------------------------------------------ 1. Confirm which layer is rejecting the request. nginx logs the intended body size when it refuses, so its absence tells you the rejection happened upstream. $ grep 'too large body' /var/log/nginx/error.log | tail -5 2. Print the configuration nginx has actually loaded, including every include, and look for competing definitions rather than assuming the file you edited is the one in force. $ nginx -T 2>/dev/null | grep -n 'client_max_body_size' 3. Set the limit in the block that handles uploads, and keep it consistent with any outer value so the specific one is not accidentally smaller. http { client_max_body_size 50m; # sensible ceiling for the whole server server { location /api/upload { client_max_body_size 200m; # larger only where genuinely needed proxy_pass http://app; } } } note: A value of 0 disables the check entirely. That turns a bounded rejection into an unbounded one, so prefer a real ceiling over removing it. 4. Reload rather than restart, after testing the configuration parses. $ nginx -t && nginx -s reload 5. On Kubernetes, set it on the Ingress. Editing the controller's generated config is undone on the next reconcile. metadata: annotations: nginx.ingress.kubernetes.io/proxy-body-size: "200m" 6. Raise the application's own limit to match, and expect the failure to reappear there once nginx stops rejecting. Both layers have to agree. // Express app.use(express.json({ limit: "200mb" })); // PHP — php.ini // upload_max_filesize = 200M // post_max_size = 200M VERIFY: An upload just under the new limit succeeds end to end, one just over it is rejected with 413 by the layer you configured, and the nginx error log names the expected boundary rather than 1048576. FALLBACK: For genuinely large files, stop proxying the body at all: issue a pre-signed URL and have the client upload directly to object storage. That removes the limit question from every layer instead of raising it in each. APPLIES TO ------------------------------------------------------------------------ nginx: all versions (client_max_body_size defaults to 1m and applies in http, server and location contexts.) ingress-nginx: all versions (Configured through the proxy-body-size annotation rather than nginx.conf.) platforms: linux NOT APPLICABLE TO ------------------------------------------------------------------------ - 408 Request Timeout, where the body is slow rather than large - 431 Request Header Fields Too Large, which concerns headers and is governed by different directives - Application-level upload limits that return the framework's own error rather than 413 from nginx - Apache's LimitRequestBody, which produces the same status from an unrelated configuration EVIDENCE ------------------------------------------------------------------------ 1. nginx — ngx_http_core_module, client_max_body_size https://nginx.org/en/docs/http/ngx_http_core_module.html nginx | official-docs | read 2026-08-08 supports: That client_max_body_size governs the maximum request body, defaults to 1m, and is valid in http, server and location contexts — which is what makes the wrong-context case possible. 2. 413 Content Too Large https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/413 MDN Web Docs | official-docs | read 2026-08-08 supports: That 413 means the request entity exceeded a server-defined limit — so any layer in the chain may legitimately emit it, which is why identifying the layer comes before changing configuration. CONFIDENCE ------------------------------------------------------------------------ medium — The directive's meaning, its 1m default and its valid contexts are quoted from nginx's own module reference, and the status semantics from MDN. Confidence is medium rather than high because it rests on two sources: the ingress annotation name and the framework-side limits are drawn from the respective projects' conventions rather than quoted here, and the layer-identification method is diagnostic practice. ------------------------------------------------------------------------ knowbase 0.1.0 — CC-BY-4.0