nginx 413 on a Sume run webhook: raise client_max_body_size
nginx rejects bodies over client_max_body_size, default 1m, with 413. A Sume run receipt can reach 1 MiB, so set the limit on the webhook location and test it.

If your Sume webhook receiver sits behind nginx, set client_max_body_size 2m; on the webhook location. nginx's documentation gives the directive a default of 1m and says a request whose Content-Length is larger gets a 413 (Request Entity Too Large) error (read 2026-10-04). Sume's run webhooks cap a delivered receipt at 1 MiB, which is 1,048,576 bytes, and a body near that cap is on the edge of nginx's default.
A 413 from your proxy is a non-2xx answer, so Sume counts it as a failed attempt and retries, up to 10 times. Your application never sees the request, so no application log explains it. The symptom is a receiver that works for small runs and goes quiet for the biggest ones.
What exactly does Sume send, and how big can it be?
Run webhooks deliver the same receipt the poll endpoint returns, wrapped in an envelope. When the serialized receipt exceeds 1 MiB, Sume sends payload: null and an error.code of payload_too_large instead, and you read the full receipt from result_url. So the largest body you will receive is just over 1 MiB including the envelope, and the safe nginx limit has some headroom above it.
Job webhooks are smaller, but one limit on one path is easier to remember than two.
What does the config look like?
Scope the larger limit to the one path rather than raising it for the whole server. Keep the proxy from buffering to a temp file only if you have a reason; the default is fine.
server {
listen 443 ssl;
server_name hooks.example.com;
location = /hooks/sume {
client_max_body_size 2m; # Sume receipts reach 1 MiB
proxy_read_timeout 10s; # Sume gives up at 10 s per attempt
proxy_pass http://127.0.0.1:3000;
}
# every other route keeps the 1m default
}
# verify the limit without Sume:
# head -c 1500000 /dev/zero | curl -s -o /dev/null -w '%{http_code}\n' \
# --data-binary @- https://hooks.example.com/hooks/sumeWhich limits sit between Sume and your handler?
| Layer | Limit to check | Source |
|---|---|---|
| Sume delivery | 1 MiB receipt cap, then payload null | Sume run webhooks docs |
| Sume delivery | 10 s timeout per attempt, no redirects followed | Sume webhooks docs |
| nginx | client_max_body_size, default 1m | nginx core module docs |
| Your framework | Its own JSON or raw body limit | Check your framework docs |
| Your handler | Respond 2xx before any slow work | Your code |
How do you know it is fixed?
Test the limit with a body you generate yourself, as in the comment above: a 1.5 MB body should return your handler's status (a 401 for a bad signature is fine) and not 413. Then check the delivery receipts for the endpoint in the dashboard and the polling endpoint for any run that retried.
- Look in the nginx error log for
client intended to send too large body. - Raise the limit in every proxy in the chain: a CDN or load balancer in front of nginx has its own cap.
- Do not set
client_max_body_size 0, which turns the check off for the path.
Sources
Related posts
More in Developers
- No seed on Sume video models: rerun a prompt reproducibly
Sume video models reject a seed field, so a rerun is a new take. For repeatable results store the finished clip, and use Idempotency-Key for safe retries.
- Node 24.21 MIMEType.parse: validate a Sume artifact content type
Node 24.21.0 adds a non-throwing MIMEType.parse. Use it, with a try/catch fallback for older Node, to check a Sume artifact's content_type before saving.
- Which Node versions to test the Sume SDK on: 22, 24 and 26
Node 26.10.0 is Current, 24.21.0 and 22.23.3 are LTS. A small CI matrix and smoke test for code that calls the Sume API with fetch and WebCrypto.
- Node 26.10 fs.openAsBlobSync: upload a local file with Sume uploadFile
Node 26.10 adds fs.openAsBlobSync. Open a file as a typed Blob and pass it to the Sume SDK's uploadFile to get a durable HTTPS URL for a Format input.
Written by Sume