/인프라/nginx 413 Request Entity Too Large: A 5-Minute Diagnosis and Fix Guide
Infrastructurenginx 413client_max_body_size

nginx 413 Request Entity Too Large: A 5-Minute Diagnosis and Fix Guide

A copy-paste guide to clear nginx upload 413 Request Entity Too Large in five minutes: check error.log, reproduce with curl, set client_max_body_size in the right place, and align PHP, ingress, and CDN.

nginx 413 Request Entity Too Large: A 5-Minute Diagnosis and Fix Guide

nginx 413 Request Entity Too Large: A 5-Minute Diagnosis and Fix Guide

If you are in the middle of an incident, start here: If nginx error.log shows client intended to send too large body, it is 99% a client_max_body_size problem (default 1MB). Put client_max_body_size 50m; in the location block that handles uploads, then run nginx -t && systemctl reload nginx. Below we cover the exact placement plus every other layer that can still block you—all in five minutes.

Uploads that worked a minute ago suddenly return 413?

When the ticket is “image uploads were fine yesterday and suddenly broke today,” look at the status code first. 413 is fundamentally different from 502/504.

  • 502/504: The gateway cut the connection because the upstream is down or too slow (a backend problem)
  • 413 Request Entity Too Large: The request body the client sent is too large, so nginx aborted before it even finished reading the body

So 413 can fire even when the backend is healthy. The usual reason it “suddenly” happens is that uploaded file size crossed the limit. A 1MB thumbnail goes through; a 1.2MB photo does not.

This article covers 413 caused by request body size only. For 504/502 (timeouts, upstream down), see the separate guide (nginx 502/504 troubleshooting).

Why 413 fires: the mechanism

nginx has a client_max_body_size directive whose default is only 1MB. When a request arrives, nginx looks at the Content-Length header (or the accumulated size of a multipart body) and, the moment that limit is exceeded, it stops reading the body and immediately responds with 413.

The request is not rejected at a single point. Body-size limits exist at several layers.

CODE
Browser ──> CDN/WAF ──> nginx ──> reverse proxy ──> upstream (PHP/app)
            (body limit)  (1MB)     (proxy limit)     (post_max_size, etc.)

If any one of those limits is too small, 413 is returned there. So the key is to pin down which layer blocked the request first.

5-minute diagnosis routine

① Check one line in error.log

Bash
tail -f /var/log/nginx/error.log | grep "too large body"

If you see a line like this, nginx is the culprit.

CODE
*123 client intended to send too large body: 3145728 bytes

② Reproduce with curl

Bash
curl -v -F "file=@/path/big.jpg" https://example.com/upload

Use -v to inspect the response in detail. Two things matter:

  • Status code: HTTP/1.1 413 Request Entity Too Large
  • Server header: Server: nginx means nginx, Server: cloudflare means CDN/WAF, anything else may be the upstream

③ Identify which layer is blocking

Response body messageServer headerWho is blockingAction
413 Request Entity Too LargenginxnginxRaise client_max_body_size
413 Payload Too Largeapp/frameworkupstream (app)post_max_size, app limits
413 + cloudflare/WAFCDN/WAFfront layerCDN body-size policy

Check the currently applied nginx value like this.

Bash
nginx -T | grep client_max_body_size

If nothing is printed, the default of 1MB is in effect.

Fixes by layer

nginx: which block to put it in

client_max_body_size is inherited httpserverlocation, and overridden by a more specific block. The safest approach is to set a large value only on the upload endpoint location.

Nginx
http {
    client_max_body_size 1m;          # keep global small

    server {
        server_name example.com;
        client_max_body_size 10m;     # default for this server

        location /upload {
            client_max_body_size 50m; # allow large uploads only here
        }
    }
}

With the config above, /upload allows up to 50MB, other paths on this server 10MB, and other servers 1MB. Always syntax-check, then reload.

Bash
nginx -t && systemctl reload nginx

If you are on Kubernetes (nginx-ingress)

In container environments the same issue often comes back because of a missing annotation. Add this to the Ingress:

YAML
metadata:
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"

Align the upstream as well

Raising nginx alone still yields 413 if the upstream blocks. The recommended alignment is nginx ≥ post_max_size ≥ upload_max_filesize.

TargetSettingExampleNotes
nginxclient_max_body_size50mOutermost, largest
PHPpost_max_size50MEntire POST body
PHPupload_max_filesize48MPer-file
ApacheLimitRequestBody52428800In bytes
nginx→FastCGIfastcgi_buffers, etc.sized appropriatelyTemp files if buffers are too small

If you raise nginx to 50m but leave PHP post_max_size at 2M, nginx lets the request through, then PHP discards the body and $_FILES comes back as an empty array—a classic trap.

The danger of client_max_body_size 0

0 means unlimited. Never set it globally. An attacker can send a multi-GB body, exhaust disk and memory, and take the service down.

When multipart and timeouts fire together

Large uploads can hit size limits and time limits at the same time. The body limit may be large enough, but a slow link stretches the transfer until client_body_timeout (default 60s) fires, producing a 408 or a dropped connection.

Nginx
location /upload {
    client_max_body_size 50m;
    client_body_timeout 120s;   # allow slow uploads
}

413 (size) and timeouts (time) are different directives—check both. If the response is 502/504, this article is not the one you need; troubleshoot the upstream instead.

A note from the field

After enough incidents, the pattern is clear: 80% of 413 tickets become a second outage because “we fixed nginx but not PHP/the proxy.” It also comes back right after a new CDN is attached, or after a deploy that forgot the ingress annotation. So when I fix a 413 I always use a checklist: write down every body-size limit on the path (browser → CDN → nginx → app) and align them in one pass. Fix only one layer and you will meet this again next week.

Recurrence-prevention and security checklist

  • Never use client_max_body_size 0 (unlimited)
  • Apply large values only on the upload location; keep the global default small
  • Confirm nginx ≥ post_max_sizeupload_max_filesize
  • On Kubernetes, confirm the proxy-body-size annotation
  • Check any separate body-size limit on the CDN/WAF in front
  • Apply auth, extension checks, and virus scanning on the upload endpoint
  • Monitor and alert on temp-directory disk exhaustion

References: official docs

The primary source for the behavior, settings, and errors in this article is the official documentation below. Check version-specific options and exact behavior there.

FAQ

Q. I changed client_max_body_size and still get 413. A. Check where it was applied. Use nginx -T | grep client_max_body_size to see the actually loaded value, and verify whether the upload location inherits from a different server or parent block. Also suspect ingress/CDN front-end limits and PHP post_max_size.

Q. How do I tell 413 from 504? A. 413 means “body too large”—nginx aborts immediately. 504 means the upstream is slow or dead. Distinguish them by status code and whether error.log contains too large body. For 504, see the separate guide.

Q. Do I have to restart nginx to apply the change? A. A restart is not required. Validate syntax with nginx -t, then do a zero-downtime reload with systemctl reload nginx.

확인 정보
✦ ✦ ✦
편집 검토 · Editorial Review

Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.

편집 책임 · Nodelog 기술 편집팀·발행 · ·업데이트 ·

Comments

Be the first to comment.