How to Return Structured API Errors with RFC 9457 Problem Details
When an HTTP API returns an error, its status code tells the client the general result, but not always what went wrong…
When an API rejects a file upload with HTTP 413, the request body has exceeded a size limit enforced by the server or by an intermediary, such as a proxy or gateway. The request body is the data sent with the request, including the file and any accompanying upload-format information. For a fixed size limit, the upload fails until you lower the amount of data sent or raise the limit at the layer that rejected it.
First find which part of the request path returned the error. Then change that part’s limit or change how the client sends the file. The fix depends on your hosting setup because nginx, PHP, IIS, and API gateways use different settings.
An API request can pass through several components before it reaches the code that handles the upload. A reverse proxy (a server that forwards requests to another server), a web server, the runtime (the environment that runs the API code), or a managed gateway can reject the request before the API reads the file. Each component can enforce its own size limit, so changing one setting will not help if a different component still blocks the request.
Look for clues in the response body and headers, then compare the request with logs from the proxy, web server, and API to find which component logged the rejection and whose limit needs attention. If the logs do not make the source clear, test the same upload against the API through a path that bypasses one intermediary at a time, where your setup permits it.
Also compare the total request size with the file size. A multipart upload sends the file and other form data in separate parts, with boundary markers between them. This makes the full request slightly larger than the file itself. Set client-side validation below the server’s maximum to leave room for that overhead. Validation can prevent users from sending files the API will reject, but it does not replace server-side limits.
For nginx, check the client_max_body_size directive in the configuration that handles the API request. Raising that setting resolves a 413 when nginx’s limit caused the rejection, as shown in nginx configuration examples. If nginx forwards the request to another server, check that server’s limit too.
PHP APIs have separate settings for the total POST body and an individual uploaded file. Check both post_max_size and upload_max_filesize; a limit in either setting can prevent a larger upload from reaching the PHP code. Some hosts ignore runtime ini_set changes, so confirm that your changes took effect in the host’s PHP configuration or ask the provider to update it. The PHP upload-limit guidance describes these configuration options and hosting constraints.
For an ASP.NET Core application hosted on IIS, check IIS’s maxAllowedContentLength. With in-process hosting, also check IISServerOptions.MaxRequestBodySize; both limits apply. With out-of-process hosting behind the ASP.NET Core Module, IIS sets the limit and Kestrel’s request body size limit is disabled. See Microsoft’s upload guidance and Kestrel configuration documentation.
Managed gateways have limits that operators cannot always change. AWS API Gateway, for example, has a fixed request payload limit. For files that exceed it, AWS recommends using Amazon S3 as the upload destination rather than sending the file through API Gateway (AWS discussion of the payload limit).
Raising a limit also means the server must accept and handle larger requests. Before increasing it, choose a maximum that matches the files your API needs to support and consider the resources required to receive and process them. If a gateway’s cap or the server’s resource constraints make a higher limit unsuitable, change the upload design instead.
For large uploads, send the file directly to a storage service or divide it into chunks. AWS recommends S3 as the destination for files that exceed API Gateway’s request limit. Direct uploads keep the file data out of the API gateway request, while the API can handle related application data separately.
Chunked uploads split a file into smaller pieces that the server receives and puts back together. This approach works only when the server supports chunk handling and tracks which pieces belong to the same upload. It adds server-side work for managing upload sessions and reassembling the file, as described in this large-file upload design discussion. Choose chunking when the API can support that complexity and the file size or connection reliability calls for it.
Sending the same request again does not reduce its size, so a fixed size limit will reject it again. A 413 response can also describe a temporary condition. If the server sends Retry-After, wait until the indicated time before trying again, as described in RFC 9110. Google Cloud Storage, for example, does not list HTTP 413 as a retryable response in its retry guidance. After a 413, return a useful error to the client and identify the maximum accepted size when the API knows it. For a fixed size limit, the client should reduce the upload, choose another upload path, or report the limit to the user rather than retry unchanged data.
Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.
Take a look at vroni.com