Kestrel Return 504 while frequently encountered with the "request body too large" problem
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
### Describe the bug
Use the **RequestSizeLimitAttribute** together with **IFormFile** on an WebApi action method. The expected behaviour when
the request body is too large is to return a 500 internal server error and tell me the request body is too large. However, if the client frequently (e.g. 1 request each second) send files larger than the limit, the kestrel will probably return 504 with 0 byte in response.
### To Reproduce
It's very easy to reproduce.
1. Simply create a default asp.net core 3.1 webapi project,
2. Add a new action in any controller like below:
```csharp
[HttpPost]
[RequestSizeLimit(4194304)]
public ActionResult Post(IFormFile video)
{
return Ok();
}
```
3. Start the api using kestrel as the host (release mode and without debugger attached (Ctrl + F5)).
4. Upload any file larger than 4M using postman or fiddler, you will probably find the 504 response in 10 times.
I also upload the code here: https://github.com/stg609/Issue23840
### Exceptions (if any)
## Postman
I get below snapshot using Postman.


## Fiddler
I get below snapshot using Fiddler to send the request, as you can see, there're multiple 504 response.

And the raw response :
> HTTP/1.1 504 Fiddler - Receive Failure
Date: Fri, 10 Jul 2020 05:19:35 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Cache-Control: no-cache, must-revalidate
Timestamp: 13:19:35.564
> [Fiddler] ReadResponse() failed: The server did not return a complete response for this request. Server returned 0 bytes.
### Further technical details
- ASP.NET Core version: both 2.2 and 3.1 can reproduce the same issue.
- Include the output of `dotnet --info`
> .NET Core SDK(反映任何 global.json):
Version: 3.1.300
Commit: b2475c1295
> 运行时环境:
OS Name: Windows
OS Version: 10.0.17134
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\3.1.300\
> Host (useful for support):
Version: 3.1.4
Commit: 0c2e69caa6
> .NET Core SDKs installed:
2.1.502 [C:\Program Files\dotnet\sdk]
2.1.507 [C:\Program Files\dotnet\sdk]
2.2.105 [C:\Program Files\dotnet\sdk]
3.1.300 [C:\Program Files\dotnet\sdk]
> .NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
- The IDE (VS / VS Code/ VS4Mac) you're running on, and it's version
Visual Studio 2019 16.6
- The .Net Core Log for the exception if needed.
```
> dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[6]
Connection id "0HM14IN0FEJJ8" received FIN.
dbug: Microsoft.AspNetCore.Server.Kestrel[39]
Connection id "0HM14IN0FEJJ8" accepted.
dbug: Microsoft.AspNetCore.Server.Kestrel[1]
Connection id "0HM14IN0FEJJ8" started.
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7]
Connection id "0HM14IN0FEJJ8" sending FIN because: "The client closed the connection."
dbug: Microsoft.AspNetCore.Server.Kestrel[10]
Connection id "0HM14IN0FEJJ8" disconnecting.
dbug: Microsoft.AspNetCore.Server.Kestrel[2]
Connection id "0HM14IN0FEJJ8" stopped.
dbug: Microsoft.AspNetCore.Server.Kestrel[39]
Connection id "0HM14IN0FEJJ9" accepted.
dbug: Microsoft.AspNetCore.Server.Kestrel[1]
Connection id "0HM14IN0FEJJ9" started.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://localhost:5000/api/values multipart/form-data; boundary=--------------------------622998055053730425270863 4372582
trce: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[2]
All hosts are allowed.
dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001]
1 candidate(s) found for the request path '/api/values'
dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1005]
Endpoint 'WebApplication34.Controllers.ValuesController.Post (WebApplication34)' with route pattern 'api/Values' is valid for the request path '/api/values'
dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1]
Request matched endpoint 'WebApplication34.Controllers.ValuesController.Post (WebApplication34)'
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'WebApplication34.Controllers.ValuesController.Post (WebApplication34)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Route matched with {action = "Post", controller = "Values"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.ActionResult Post(Microsoft.AspNetCore.Http.IFormFile) on controller WebApplication34.Controllers.ValuesController (WebApplication34).
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of authorization filters (in the following order): Microsoft.AspNetCore.Mvc.Filters.RequestSizeLimitFilter
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of resource filters (in the following order): Microsoft.AspNetCore.Mvc.ConsumesAttribute
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of action filters (in the following order): Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter (Order: -3000), Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter (Order: -2000)
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of exception filters (in the following order): None
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Execution plan of result filters (in the following order): Microsoft.AspNetCore.Mvc.Infrastructure.ClientErrorResultFilter (Order: -2000)
trce: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Authorization Filter: Before executing OnAuthorization on filter Microsoft.AspNetCore.Mvc.Filters.RequestSizeLimitFilter.
dbug: Microsoft.AspNetCore.Mvc.Filters.RequestSizeLimitFilter[3]
The maximum request body size has been set to 4194304.
trce: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Authorization Filter: After executing OnAuthorization on filter Microsoft.AspNetCore.Mvc.Filters.RequestSizeLimitFilter.
trce: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Resource Filter: Before executing OnResourceExecuting on filter Microsoft.AspNetCore.Mvc.ConsumesAttribute.
trce: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Resource Filter: After executing OnResourceExecuting on filter Microsoft.AspNetCore.Mvc.ConsumesAttribute.
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
Executing controller factory for controller WebApplication34.Controllers.ValuesController (WebApplication34)
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed controller factory for controller WebApplication34.Controllers.ValuesController (WebApplication34)
trce: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Resource Filter: Before executing OnResourceExecuted on filter Microsoft.AspNetCore.Mvc.ConsumesAttribute.
trce: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Resource Filter: After executing OnResourceExecuted on filter Microsoft.AspNetCore.Mvc.ConsumesAttribute.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed action WebApplication34.Controllers.ValuesController.Post (WebApplication34) in 1.8187ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'WebApplication34.Controllers.ValuesController.Post (WebApplication34)'
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Request body too large.
at Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException.Throw(RequestRejectionReason reason)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.OnReadStarting()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.MessageBody.TryStart()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.ReadAsyncInternal(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken)
at Microsoft.AspNetCore.WebUtilities.BufferedReadStream.EnsureBufferedAsync(Int32 minCount, CancellationToken cancellationToken)
at Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
at Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions.DrainAsync(Stream stream, ArrayPool`1 bytePool, Nullable`1 limit, CancellationToken cancellationToken)
at Microsoft.AspNetCore.WebUtilities.MultipartReader.ReadNextSectionAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Http.Features.FormFeature.InnerReadFormAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.ModelBinding.FormValueProviderFactory.AddValueProviderAsync(ValueProviderFactoryContext context)
at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.CreateAsync(ActionContext actionContext, IList`1 factories)
at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.TryCreateAsync(ActionContext actionContext, IList`1 factories)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
Connection id "0HM14IN0FEJJ9" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 21.0949ms 500 text/plain
dbug: Microsoft.AspNetCore.Server.Kestrel[17]
Connection id "0HM14IN0FEJJ9" bad request data: "Request body too large."
Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Request body too large.
at Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException.Throw(RequestRejectionReason reason)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.OnReadStarting()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.MessageBody.TryStart()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.MessageBody.ConsumeAsync()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application)
dbug: Microsoft.AspNetCore.Server.Kestrel[10]
Connection id "0HM14IN0FEJJ9" disconnecting.
dbug: Microsoft.AspNetCore.Server.Kestrel[2]
Connection id "0HM14IN0FEJJ9" stopped.
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7]
Connection id "0HM14IN0FEJJ9" sending FIN because: "The Socket transport's send loop completed gracefully."
```
Contributor guide
Research direction
Start with the linked minimal ASP.NET Core 3.1 repro and reproduce repeated oversized multipart uploads against the action using RequestSizeLimitAttribute and IFormFile. Trace the Kestrel BadHttpRequestException path shown in the log, then inspect related request-body handling and tests. Done means repeated requests produce a complete, consistent response instead of an empty 504.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- api, backend, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100