BadHttpRequestException: Request body too large. The max request body size is
30000000 bytes. means an upload was bigger than Kestrel's request body limit,
which the message shows as 30,000,000 bytes. Raise the limit for the one upload endpoint,
or for the whole server, and the same upload goes through.
Both were tested with a 31,000,000-byte file: a RequestSizeLimitAttribute on
the endpoint, and Limits.MaxRequestBodySize in ConfigureKestrel.
Each turned the 413 Payload Too Large into a 200.
The error
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HNPRRDSMTTEA", Request id "0HNPRRDSMTTEA:00000001": An unhandled exception was thrown by the application.
Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Request body too large. The max request body size is 30000000 bytes.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.OnReadStarting()
...
at Program.<>c.<<<Main>$>b__0_9>d.MoveNext() in C:\...\FixLab\Program.cs:line 45
...
The client saw this response:
curl.exe -s -D - -H "Content-Type: application/octet-stream" --data-binary "@big.bin" http://127.0.0.1:15720/upload
HTTP/1.1 413 Payload Too Large
Content-Length: 0
Connection: close
Date: Fri, 06 Nov 2026 07:56:32 GMT
Server: Kestrel
Why it happens
The endpoint copied the request body into memory:
app.MapPost("/upload", async (HttpRequest request) =>
{
using var ms = new MemoryStream();
await request.Body.CopyToAsync(ms);
return $"received {ms.Length} bytes";
});
The test file was 31,000,000 bytes, one million over the limit in the message. The stack
trace shows the exception thrown when the handler started reading the body
(CopyToAsync at Program.cs:line 45), and the client got a
413 with Connection: close. Nothing in the project set a limit; the
30000000 in the message is the value Kestrel used with no configuration.
The log entry reads An unhandled exception was thrown by the application
because the handler did not catch the exception. Even so the client received a 413, not
the empty 500 that other unhandled exceptions in this test project produced, so the
status code alone already points at the size of the body.
The fix
Per endpoint, which keeps the default for every other route:
app.MapPost("/upload", async (HttpRequest request) =>
{
using var ms = new MemoryStream();
await request.Body.CopyToAsync(ms);
return $"received {ms.Length} bytes";
}).WithMetadata(new Microsoft.AspNetCore.Mvc.RequestSizeLimitAttribute(100_000_000));
Or server-wide, with the endpoint unchanged:
builder.WebHost.ConfigureKestrel(o => o.Limits.MaxRequestBodySize = 100_000_000);
Both runs answered HTTP/1.1 100 Continue, then HTTP/1.1 200 OK
with received 31000000 bytes, and logged nothing after startup. The
per-endpoint attribute is the narrower change, since it is attached to the upload route
alone, while the Kestrel setting applies to the server. Pick a ceiling that fits your real
uploads rather than removing the limit.
How it was reproduced
A dotnet new web project (net10.0) with the upload endpoint above, run on
Kestrel in the Production environment on ports 15720 (broken), 15721 (per endpoint) and
15722 (server-wide). The file was made in PowerShell with
[IO.File]::Create and SetLength(31000000), and sent with curl
8.21.0. .NET SDK 10.0.403, Microsoft.AspNetCore.App 10.0.14, Windows 11. IIS and
multipart form limits were not part of this test.
Frequently asked
- What is the default max request body size in ASP.NET Core Kestrel?
- In this test the message said 30000000 bytes with no limit configured, and a 31,000,000-byte upload was refused with 413 Payload Too Large.
- How do I increase the upload size limit for one minimal API endpoint?
- Add .WithMetadata(new Microsoft.AspNetCore.Mvc.RequestSizeLimitAttribute(100_000_000)) to the MapPost call. In the test the same 31 MB upload then returned 200.
- How do I raise the request body limit for the whole Kestrel server?
- Use builder.WebHost.ConfigureKestrel(o => o.Limits.MaxRequestBodySize = 100_000_000). In the test that also let the 31 MB upload through without changing the endpoint.
More decoded errors in the Fixes category, including synchronous operations are disallowed, another error from reading a request body.