FlowKit

n8n error 413 Request Entity Too Large: the three layers to check

Published 26 August 2026 · 8 min read

A workflow that worked yesterday refuses a file today: 413 Request Entity Too Large, or in the logs PayloadTooLargeError: request entity too large. The instinct is immediate — raise the limit. Except three layers can have raised that 413: n8n itself, the reverse proxy sitting in front of it, or the remote API your HTTP Request node is calling. Most people fix one of them, restart, and hit the same error again.

This guide is a decision tree: work out who is refusing, apply the right setting, then deal with the actual cause — which is almost always that a large file should never have travelled through memory in the first place.

Diagnose before touching anything

The status code is the same everywhere, but each layer phrases it differently. Read the full response, not just the code.

  • The HTTP Request node fails with a 413: the remote server is refusing, and no local setting will change that.
  • A Webhook, a form, a workflow import or an editor upload fails: it is your stack — either n8n or the proxy.
  • The response is an HTML page titled "413 Request Entity Too Large": that is nginx (or another proxy). n8n does not render HTML for its API errors.
  • The response is JSON mentioning PayloadTooLargeError: that is n8n, through Express's body-parsing middleware.

A command-line test settles it:

# Build a 20 MB file and push it to the webhook
head -c 20000000 /dev/urandom > /tmp/test.bin
curl -v -X POST https://n8n.example.com/webhook-test/my-hook \
  -F "file=@/tmp/test.bin" 2>&1 | tail -30

Repeat with 500 KB, 5 MB, 50 MB: the threshold where it flips names the culprit. A hard stop at 1 MB points at nginx, one at 16 MB points at n8n. If nothing shows up in the container logs at all, the request never got there — the same elimination method as any workflow debugging, applied to the network layer.

This vagueness is not anecdotal. In "An Empirical Study on Configuration Errors in Commercial and Open Source Systems" (SOSP 2011), Zuoning Yin, Xiao Ma and their co-authors analysed 546 real-world misconfigurations: only 7.2% to 15.5% produce a message that explicitly pinpoints the offending parameter (see on Google Scholar). The 413 is a textbook case: a correct status code that never says which ceiling was crossed, or where.

Layer 1 — n8n and N8N_PAYLOAD_SIZE_MAX

n8n imposes its own cap on the request bodies it accepts, on webhooks as well as on its internal API. The N8N_PAYLOAD_SIZE_MAX variable is expressed in MiB and defaults to 16. The documentation notes that the instance must be restarted for the change to apply, and that a higher ceiling consumes more memory and CPU.

# docker-compose.yml
services:
  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: unless-stopped
    environment:
      - N8N_PAYLOAD_SIZE_MAX=128
      - N8N_FORMDATA_FILE_SIZE_MAX=200
      - N8N_DEFAULT_BINARY_DATA_MODE=filesystem
    volumes:
      - n8n_data:/home/node/.n8n

A second variable is often overlooked: N8N_FORMDATA_FILE_SIZE_MAX, which caps in MiB the size of files inside form-data webhook payloads, defaulting to 200. It does not replace the first one: a multipart/form-data upload has to clear both checks, which is why a 60 MB upload fails even though the form-data limit sits at 200 — N8N_PAYLOAD_SIZE_MAX, still at 16, made the call. Both belong to the Endpoints group of the environment variables reference.

In queue mode with Redis, the variable must be set identically on the main process and on every worker, otherwise failures look random depending on which worker picked up the job. And if your webhook receives a base64-encoded file inside the JSON body, remember that the encoding inflates size by roughly a third: a 12 MB PDF then exceeds 16 MB. The same limit also hits large workflow imports.

Layer 2 — the reverse proxy, culprit number one

The most frequent suspect: its defaults are far lower than n8n's.

nginx

client_max_body_size defaults to 1 MB, so any serious upload is refused before reaching n8n. The directive goes in an http, server or location block:

server {
    listen 443 ssl;
    server_name n8n.example.com;

    client_max_body_size 100M;
    client_body_timeout 300s;

    location / {
        proxy_pass http://127.0.0.1:5678;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 300s;
        proxy_request_buffering off;
    }
}

proxy_request_buffering off streams the body through instead of writing it to disk first. Reload with nginx -t && nginx -s reload, checking that no other block reintroduces a lower value (nginx in front of n8n).

Traefik

Traefik enforces no limit by default, but if you use the buffering middleware, maxRequestBodyBytes decides, in bytes. memRequestBodyBytes (1,048,576 by default) is the threshold at which the body spills to disk.

# Docker labels on the n8n service
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.n8n.rule=Host(`n8n.example.com`)"
  - "traefik.http.services.n8n.loadbalancer.server.port=5678"
  - "traefik.http.middlewares.n8n-body.buffering.maxRequestBodyBytes=104857600"
  - "traefik.http.middlewares.n8n-body.buffering.memRequestBodyBytes=2097152"
  - "traefik.http.routers.n8n.middlewares=n8n-body"

That last line is essential: a middleware declared but never attached to the router applies to nothing.

Caddy

Caddy enforces no ceiling until you declare one, through request_body:

n8n.example.com {
    request_body {
        max_size 100MB
    }
    reverse_proxy 127.0.0.1:5678
}

Past max_size, Caddy returns a 413 too. Both proxies are covered in the HTTPS and custom domain guide.

Cloudflare

If your domain is proxied (orange cloud), Cloudflare applies its own request body limit, which depends on your plan: 100 MB on Free and Pro, 200 MB on Business, 500 MB by default on Enterprise — that last ceiling being raisable through support. Beyond it, Cloudflare returns the 413 and the request never reaches your server. No local setting helps: change plan, move uploads off the proxy, or stop sending the file through.

Layer 3 — the remote API is the one refusing

When the 413 shows up in an HTTP Request node's output, the problem sits with the recipient: you do not configure their server, so there is nothing to raise. Three workarounds:

  • Split the send: instead of one POST of 5,000 records, batches of 200 through a Loop Over Items node — many APIs document a maximum batch size;
  • Use the multipart or chunked upload the API provides: most storage services expose a multi-part upload precisely so that no single request ever gets too large;
  • Send a URL rather than the file, which drops the payload to a few hundred bytes.

A remote 413 is never transient: there is no point replaying it, so reserve retries for errors that deserve them (HTTP Request retries and timeouts).

The real fix: stop moving files through memory

Raising ceilings makes the symptom go away; the cause is architectural. By default, n8n keeps binary data in memory — that is exactly what the default value of N8N_DEFAULT_BINARY_DATA_MODE means. Switching it to filesystem writes binaries to disk, under the path set by N8N_BINARY_DATA_STORAGE_PATH, and lightens the Node.js heap accordingly. The s3 and azure modes, reserved for Enterprise plans, offload storage entirely (comparison of the modes).

The corollary: binary data should never end up inside the JSON. A base64-encoded file in a field becomes ordinary JSON data, serialised and then stored in the executions database.

The most effective pattern remains the signed URL: the client does not push the file to n8n, it obtains a signed upload URL, writes straight to S3 or GCS, then calls the webhook with a plain link. No limit is ever crossed — the same reasoning as archiving files to S3.

Pushing the problem upstream this way echoes the literature on "latent" configuration. In "Early Detection of Configuration Errors to Reduce Failure Damage" (OSDI 2016), Tianyin Xu, Xinxin Jin and their co-authors show that parameters not used during initialisation — the ones that only come into play on failure, failover or a traffic spike — often have no validation code at start-up at all, and so stay "latent" until the day their wrong value causes expensive damage (see on Google Scholar). A client_max_body_size left at its default is the perfect example: it bothers nobody for six months, then breaks production on the first big file.

Sibling errors not to confuse it with

  • JavaScript heap out of memory: the request went through, but processing it saturated Node.js memory — often the direct consequence of an N8N_PAYLOAD_SIZE_MAX raised carelessly (full diagnosis);
  • 504 Gateway Timeout: the size is fine, but the transfer exceeds the proxy's deadline. That is a proxy_read_timeout that is too short, not a size ceiling;
  • Payloads that get through but bloat the database: no error at all, yet the executions table grows by several gigabytes a week — handled by pruning executions regularly.

The traps

  • Setting the variable on the wrong container: in a stack with several n8n services (main, worker, webhook), setting it on just one protects only that one;
  • Forgetting to restart: the variable is read at start-up, and a docker compose up -d without recreating the container is not always enough. Check with docker exec n8n printenv | grep PAYLOAD;
  • Putting the variable under command instead of environment: it is never exported, the container starts normally, and the setting has no effect whatsoever;
  • Mixing up MiB and bytes: n8n expects MiB (128), Traefik expects bytes (134217728), nginx accepts suffixes (100M);
  • Fixing only one layer: nginx raised to 100 MB, n8n left at 16 — the error changes shape but stays;
  • Raising instead of addressing the cause: every accepted request is buffered in memory, and if the data ends up as JSON, it inflates the executions database. Going from 16 to 512 MiB means accepting that a handful of concurrent runs can take the instance down.

The checklist, in order

  1. Proxy: client_max_body_size (nginx), buffering middleware (Traefik), request_body (Caddy), Cloudflare plan — culprit number one;
  2. n8n: N8N_PAYLOAD_SIZE_MAX and, for form-data, N8N_FORMDATA_FILE_SIZE_MAX, on every process, then restart;
  3. Binary mode: N8N_DEFAULT_BINARY_DATA_MODE=filesystem, and ban base64 from the JSON;
  4. Remote API: if the 413 comes from an HTTP Request node, split, switch to multipart, or send a URL.

Work through them one at a time, retesting after each change: it is the only way to know what actually fixed the problem, and to avoid leaving three limits raised for nothing.

Going further

413 errors mostly hit workflows that handle documents: attachments, invoices, contracts, exports. The AI Inbox Pack (€79) processes email attachments through binary properties rather than base64 in JSON, which keeps you away from the problem. For document ingestion at volume, the RAG Assistant Pack (€119) applies the same principle: the file stays in its store, and the workflow only passes references around.

FAQ

Frequently asked questions

How do I increase the maximum payload size in n8n?

Set the N8N_PAYLOAD_SIZE_MAX environment variable, expressed in MiB, whose default value is 16. For example, N8N_PAYLOAD_SIZE_MAX=128 allows request bodies up to 128 MiB. The change only takes effect after the process restarts, and in queue mode it must be applied identically on the main instance and on every worker. Be aware that the n8n documentation itself warns that larger payloads require more memory and CPU.

Why does my n8n webhook still return 413 after raising N8N_PAYLOAD_SIZE_MAX?

Because the rejection comes from a layer sitting in front of n8n. The most common culprit is nginx, whose client_max_body_size directive defaults to 1 MB: the request is refused before it ever reaches n8n. Check the response body — an nginx HTML page points at the proxy, a JSON body mentioning PayloadTooLargeError points at n8n. Traefik, Caddy and Cloudflare each have their own ceiling to check as well.

What is Cloudflare's upload limit in front of an n8n instance?

It depends on your Cloudflare plan, not on n8n: 100 MB on Free and Pro, 200 MB on Business, and 500 MB by default on Enterprise, the latter being raisable on request through support. Beyond that, Cloudflare returns the 413 itself and the request never reaches your server. No n8n environment variable works around this ceiling: you either change plan, move upload traffic off the proxy, or stop sending the file through at all.

Should I raise the limit or change the architecture?

Raising the limit is a stopgap: every accepted request is buffered in full, which weighs on instance RAM and, if the data ends up as JSON, inflates the executions database. The structural fix is to stop moving the file through n8n at all: switch N8N_DEFAULT_BINARY_DATA_MODE to filesystem so binaries leave memory, and adopt the signed-URL pattern where the client uploads to S3 and the webhook only ever receives a link a few hundred bytes long.

Bundle FlowKit Complet

€269