Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for NGINX By James Joyner IV · · 9 min read

NGINX Error Guide: '413 Request Entity Too Large' on uploads

Fix NGINX 413 Request Entity Too Large errors: tune client_max_body_size, align PHP upload limits, fix proxy body size, and place the directive in the right context.

  • #nginx
  • #troubleshooting
  • #errors
  • #uploads

Overview

A 413 Request Entity Too Large means the request body the client sent is bigger than client_max_body_size, so NGINX rejects it before passing it to the backend. This is NGINX doing exactly what it was told — the default limit is 1 MB, which is smaller than most file uploads.

The rejection is logged clearly:

2026/06/23 15:04:09 [error] 4015#4015: *30188 client intended to send too large body: 5242880 bytes, client: 203.0.113.55, server: app.example.com, request: "POST /upload HTTP/1.1", host: "app.example.com"

The number (5242880 bytes = 5 MB here) is the size the client tried to send. NGINX closes the request with 413 without ever forwarding the body upstream. The fix is to raise the limit in the correct context — and to keep the backend’s own upload limits in sync.

Symptoms

  • File or form uploads fail with “413 Request Entity Too Large”.
  • error.log records client intended to send too large body.
  • Small uploads work; only files above a threshold (often 1 MB) fail.
  • The backend never logs the request — NGINX rejected it before proxying.
curl -sI -X POST -F file=@bigfile.zip https://app.example.com/upload | head -1
HTTP/1.1 413 Request Entity Too Large
sudo grep "too large body" /var/log/nginx/error.log | tail -3
[error] 4015#4015: *30188 client intended to send too large body: 5242880 bytes, request: "POST /upload HTTP/1.1"

Common Root Causes

1. client_max_body_size is unset (default 1 MB)

If you never set the directive, NGINX uses its 1 MB default and rejects anything larger.

grep -RnE 'client_max_body_size' /etc/nginx/nginx.conf /etc/nginx/conf.d/ /etc/nginx/sites-enabled/
(no output — directive is not set anywhere)
[error] 4015#4015: *30188 client intended to send too large body: 2097152 bytes

No match means the 1 MB default applies. A 2 MB upload (2097152 bytes) is refused.

2. The directive is set, but too low for real uploads

It is configured, just below what users actually upload.

grep -RnE 'client_max_body_size' /etc/nginx/
/etc/nginx/conf.d/app.conf:12:    client_max_body_size 2m;
[error] 4015#4015: *30188 client intended to send too large body: 5242880 bytes

A 5 MB upload exceeds the 2 MB cap. Raise it to cover your real maximum (for example client_max_body_size 50m;).

3. Directive in the wrong context / overridden by a more specific block

client_max_body_size set in http {} can be overridden by a server {} or location {} that sets a lower value (or none, inheriting differently than you expect).

grep -RnB2 'client_max_body_size' /etc/nginx/conf.d/ /etc/nginx/sites-enabled/
http  { client_max_body_size 100m; }
server {
    location /upload {
        client_max_body_size 1m;   # overrides the http-level 100m here
    }
}

The upload location re-declares a 1 MB limit that wins over the global 100 MB.

4. Backend (PHP) upload limits lower than NGINX

Even after NGINX accepts the body, PHP can reject it via upload_max_filesize / post_max_size. The symptom differs (the backend errors, not 413), but it is the same class of “limit too low” problem and often discovered together.

grep -E 'upload_max_filesize|post_max_size' /etc/php/8.2/fpm/php.ini
upload_max_filesize = 2M
post_max_size = 8M

If NGINX now allows 50 MB but PHP caps post_max_size at 8 MB, the upload fails at the PHP layer. Raise both to match.

5. proxy_request_buffering off without an upstream limit

With buffering off, NGINX streams the body to the upstream as it arrives; client_max_body_size still applies, and a misread of how it interacts with the backend can cause confusion about where the 413 comes from.

grep -RnE 'proxy_request_buffering|client_max_body_size' /etc/nginx/conf.d/
[error] 4015#4015: *30210 client intended to send too large body: 73400320 bytes, request: "PUT /v1/objects/large"

Even when streaming, NGINX enforces client_max_body_size (here 70 MB exceeds the cap). Set it high enough for streamed objects.

6. A reload was never done after editing the config

The config was raised but the running NGINX still has the old value because it was not reloaded.

grep -RnE 'client_max_body_size' /etc/nginx/conf.d/app.conf
sudo systemctl status nginx | grep -i 'active\|since'
client_max_body_size 50m;      # on disk
[error] 4015#4015: *30230 client intended to send too large body: 10485760 bytes

The file says 50 MB but a 10 MB upload still fails — the worker is running the pre-edit config. A reload applies the new value.

Diagnostic Workflow

Step 1: Confirm 413 and the size the client sent

curl -sI -X POST -F file=@bigfile.zip https://app.example.com/upload | head -1
sudo grep "too large body" /var/log/nginx/error.log | tail -3

The log line gives the exact byte count — that is the minimum your limit must exceed.

Step 2: Find every client_max_body_size and its context

grep -RnB2 'client_max_body_size' /etc/nginx/nginx.conf /etc/nginx/conf.d/ /etc/nginx/sites-enabled/

Note whether it is in http, server, or location. The most specific block serving the upload URL wins.

Step 3: Set or raise it in the right place

Put the value where it covers the upload route — typically the server block, or the specific upload location:

server {
    client_max_body_size 50m;   # covers all locations in this server
    ...
}

Use a value comfortably above your real maximum upload.

Step 4: Align the backend limits

grep -E 'upload_max_filesize|post_max_size|memory_limit' /etc/php/8.2/fpm/php.ini

Set upload_max_filesize and post_max_size at least as high as NGINX’s limit so the body is not rejected one layer down.

Step 5: Validate and reload (not just save)

sudo nginx -t
sudo systemctl reload nginx
# if you changed PHP limits:
sudo systemctl reload php8.2-fpm

The reload is what actually applies the new limit to live traffic.

Example Root Cause Analysis

Users report that uploading PDFs larger than ~2 MB to /upload fails with 413, while smaller files succeed.

The error log confirms the size and route:

[error] 4015#4015: *30188 client intended to send too large body: 4718592 bytes, request: "POST /upload HTTP/1.1"

Searching the config with context:

grep -RnB2 'client_max_body_size' /etc/nginx/conf.d/ /etc/nginx/sites-enabled/
/etc/nginx/conf.d/app.conf-18-    location /upload {
/etc/nginx/conf.d/app.conf:20:        client_max_body_size 2m;

There is a client_max_body_size 2m; scoped to the /upload location that overrides a higher value set at the http level. A 4.5 MB PDF exceeds it.

Fix: raise the limit on the upload location to cover real files, align PHP, validate, and reload:

# set client_max_body_size 50m; in location /upload, then:
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl reload php8.2-fpm   # after raising post_max_size to 50M

Large uploads now succeed.

Prevention Best Practices

  • Set client_max_body_size deliberately in the server (or upload location) block to your real maximum, plus headroom — never rely on the 1 MB default for anything that takes uploads.
  • Keep NGINX and backend limits in lockstep: post_max_size and upload_max_filesize in PHP (or the app’s equivalent) should be >= the NGINX value, so a large body never gets rejected one layer deeper.
  • Audit for stray location-level overrides; a low limit in a specific block silently defeats a generous global one.
  • Return a friendly client-side error before the upload starts (check file size in JS) so users get instant feedback instead of a 413 after a long upload.
  • Always nginx -t && systemctl reload nginx after editing — saving the file alone does nothing until the worker reloads.
  • For triage when 413s spike after a config change, the free incident assistant can correlate the rejected body sizes with the active limit. More fixes live in the NGINX guides.

Quick Command Reference

# Confirm 413 and the rejected size
curl -sI -X POST -F file=@bigfile.zip https://app.example.com/upload | head -1
sudo grep "too large body" /var/log/nginx/error.log | tail -3

# Find every client_max_body_size and its context
grep -RnB2 'client_max_body_size' /etc/nginx/nginx.conf /etc/nginx/conf.d/ /etc/nginx/sites-enabled/

# Check backend (PHP) upload limits
grep -E 'upload_max_filesize|post_max_size|memory_limit' /etc/php/8.2/fpm/php.ini

# Validate and reload after raising limits
sudo nginx -t && sudo systemctl reload nginx
sudo systemctl reload php8.2-fpm

Conclusion

A 413 is NGINX enforcing client_max_body_size against a body that exceeds it. The usual root causes:

  1. The directive is unset, so the 1 MB default rejects ordinary uploads.
  2. It is set but lower than your real maximum upload.
  3. A more specific server/location block overrides a generous global value.
  4. The backend’s own limits (post_max_size, upload_max_filesize) are lower than NGINX.
  5. Streamed bodies (proxy_request_buffering off) still hit the limit.
  6. The config was edited but never reloaded.

Read the rejected byte count in error.log, set client_max_body_size above it in the right context, align the backend limits, then validate and reload. Both layers must agree, or the upload fails at whichever is lower.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.