Skip to content

Unexpected end of Stream, the content may have already been read by another component.  #18087

@tester346

Description

@tester346

I have some weird problem which happens to only 1 user of let's say 50

When he uploads file there's Unexpected end of Stream, the content may have already been read by another component. at Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions.DrainAsync(Stream stream, ArrayPool1 bytePool, Nullable1 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, IList1 factories) at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.CreateAsync(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()
` being thrown

Here's my endpoint:

[HttpPost]
public async Task<JsonResult> UploadFile(IFormFile file, int type, string otherParam)

The thing is that I have middleware which logs every request, so it is reading requests and setting body position to 0 in order to be able to use request data later

public async Task Invoke(HttpContext ctx)
{
    var request = await FormatRequest(ctx.Request, ctx);
    Log.Information(request);
    await next(ctx);
}

private async Task<string> FormatRequest(HttpRequest request, HttpContext ctx)
{
    //This line allows us to set the reader for the request back at the beginning of its stream.
    request.EnableRewind();

    //We now need to read the request stream.  First, we create a new byte[] with the same length as the request stream...
    var length = Convert.ToInt32(request.ContentLength);

    if (length > 30000)
        return $"file of length: {length}";

    var buffer = new byte[length];

    //...Then we copy the entire request stream into the new buffer.
    await request.Body.ReadAsync(buffer, 0, buffer.Length);

    //We convert the byte[] into a string using UTF8 encoding...
    var bodyAsText = Encoding.UTF8.GetString(buffer);

    //..and finally, assign the read body back to the request body, which is allowed because of // EnableRewind()
    request.Body.Position = 0;

    return $"User: '{ctx?.User?.Identity?.Name}' {Environment.NewLine} {request.Scheme} {request.Host}{request.Path} {Environment.NewLine} {request.QueryString} {Environment.NewLine} {bodyAsText}";
}

I thought that early return in

if (length > 30000)
    return $"file of length: {length}";

may cause problems, but when file's too large, then I'm receiving Request body too large.

I Increased

.UseKestrel(x =>
{
	x.Limits.MaxRequestBodySize = 100_000_000;
})

and now I'm able to upload "huge files" fine, so that

if (length > 30000)
    return $"file of length: {length}";

isn't causing this problem, but original problem Unexpected end of Stream, the content may have already been read by another component. still probably remains.

Anybody has an idea what may go wrong? or how to debug that?
I'm unable to reproduce it on any (dev/prod/beta) environment., but I see this exception in logs. It only occurs when that user uploads file. AFAIK he's using Chrome.

.NET Core 2.1

We're posting those files via JS.

I've seen that solution:

https://stackoverflow.com/questions/49867343/unexpected-end-of-stream-the-content-may-have-already-been-read-by-another-comp

But if there was problem with lack of DisableFormValueModelBinding then wouldn't every upload request fail this way?

Metadata

Metadata

Assignees

No one assigned

    Labels

    affected-fewThis issue impacts only small number of customersarea-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templatesbugThis issue describes a behavior which is not expected - a bug.investigateseverity-nice-to-haveThis label is used by an internal tool

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions