Kubernetes ingress returns 413 on file upload because proxy-body-size defaults to 1m
Kubernetes ingress returns 413 on file upload because proxy-body-size defaults to 1m
A customer uploads a 6 MB scanned PDF, the browser shows 413 Request Entity Too Large, and the request never reaches your app. Your application logs are empty, support retries the upload, and you spend time proving the pod is healthy when the rejection is happening one hop earlier.
In ingress-nginx, the relevant setting is proxy-body-size, and its default is 1m [link needed]. Any upload larger than that can be rejected by the ingress before your service sees it. The fix is small, but it should be deliberate.
Confirm the ingress is rejecting the request
Start by checking where the 413 is produced. A 413 from the ingress usually appears without a matching application request log or exception. Inspect the ingress controller logs for the request path and status:
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller --tail=200
Then describe the Ingress and check for an existing body-size annotation:
kubectl describe ingress my-app -n my-ns
If the app also enforces multipart or body limits, confirm those separately. A Kubernetes ingress 413 proxy-body-size problem is fixed at the ingress, but the app can still return its own 413 afterward.
Fix Kubernetes ingress 413 proxy-body-size errors
The ingress-nginx annotation is nginx.ingress.kubernetes.io/proxy-body-size [link needed]. Set it on the specific Ingress that handles uploads, not everywhere by default:
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "8m"
Use a value slightly above your real maximum upload size. Do not set 0 unless you intentionally want to disable the body-size check [link needed]. For controller-wide changes, the ConfigMap key is proxy-body-size [link needed], but per-Ingress annotations are easier to review.
Apply and verify with a numbered procedure
1. Choose the upload route and the maximum allowed size, for example 8m for a 6 MB limit.
2. Add the annotation to that Ingress only.
3. Apply the manifest:
```bash
kubectl apply -f ingress.yaml
```
4. Watch the ingress controller logs for reload or configuration errors.
5. Upload a file just under the new limit and confirm it reaches the app.
6. Upload a file over the limit and confirm the 413 still appears.
7. Check application body limits, timeouts, and storage quotas so the request is not rejected later.
If you use the controller ConfigMap instead, patch it and verify that the controller reloads:
kubectl -n ingress-nginx patch configmap ingress-nginx-controller \
--type merge \
-p '{"data":{"proxy-body-size":"8m"}}'
A controller-wide change affects every Ingress. Record the value and why it was chosen, or the next person will either lower it too far or raise it without a limit.
When NOT to do this
Do not raise proxy-body-size globally just because one route needs large uploads; that weakens a useful guardrail for every other route. Do not set a huge value if your app, object storage, or worker memory cannot handle large bodies. Do not treat the annotation as a substitute for application validation, timeouts, or virus scanning. And if the 413 comes from the app after the request reaches the pod, changing ingress settings will not fix it.
Checklist
- Confirm the 413 is from the ingress, not the app.
- Set
proxy-body-sizeon the smallest useful scope. - Keep the value close to the real upload limit.
- Apply the change and watch controller reloads.
- Test under-limit and over-limit uploads.
- Check app body limits, timeouts, and storage.
- Document the chosen value and owner.