Skip to content

S3 - OpenStreamAsync/GetObjectAsync randomly end with "The response ended prematurely with at least X bytes expected" #3674

Closed as not planned
@Rayzbam

Description

@Rayzbam

Describe the bug

When we upload big file ( > 200Mb in our usecase ) we, randomly, have an issue if we try to get the stream right after upload it on the S3 Storage

We're using the TransferUtility methods as follow :

async Task UploadAsync(AmazonS3Client client, string bucket, string storageName, Stream documentStream)
{
    var transferUtility = new TransferUtility(client);
    var request = new TransferUtilityUploadRequest { AutoCloseStream = false, BucketName = bucket, Key = storageName, InputStream = documentStream };
    var lastPercentage = 0;
    request.UploadProgressEvent += (s, e) => Request_UploadProgressEvent(s, e, ref lastPercentage);
    await transferUtility.UploadAsync(request, CancellationToken.None);
}

async Task<Stream> GetStreamAsync(AmazonS3Client client, string bucket, string storageName)
{
    var metadata = await client.GetObjectMetadataAsync(bucket, storageName);
    if (metadata.PartsCount.HasValue)
        Console.WriteLine($"Part count is {metadata.PartsCount}");

    var transferUtility = new TransferUtility(client);
    var stream = await transferUtility.OpenStreamAsync(bucket, storageName, CancellationToken.None);
    return stream;
}

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected Behavior

I want to be able to work with the stream of a blob i just uploaded without getting any exception.

Current Behavior

We encountered different exceptions according to the operations we're doing with the stream.
The first one is a simple CopyToAsync to a local MemoryStream

System.Net.Http.HttpIOException: The response ended prematurely. (ResponseEnded)
   at System.Net.Http.HttpConnection.FillAsync(Boolean async)
   at System.Net.Http.HttpConnection.CopyToContentLengthAsync(Stream destination, Boolean async, UInt64 length, Int32 bufferSize, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnection.ContentLengthReadStream.CompleteCopyToAsync(Task copyTask, CancellationToken cancellationToken)
   at Program.<Main>$(String[] args) in _localRepo__\Program.cs:line 44
   at Program.<Main>(String[] args)

The second one is clearly the same but we're trying to broadcast the stream directly to an Azure Storage :

The response ended prematurely, with at least 97892332 additional bytes expected. (ResponseEnded)

And if i'm not using a custom HTTPHandlerFactory

System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..
 ---> System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.
   --- End of inner exception stack trace ---
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
   at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at System.Net.Http.HttpConnection.FillAsync(Boolean async)
   at System.Net.Http.HttpConnection.CopyToContentLengthAsync(Stream destination, Boolean async, UInt64 length, Int32 bufferSize, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnection.ContentLengthReadStream.CompleteCopyToAsync(Task copyTask, CancellationToken cancellationToken)

Reproduction Steps

My only usecase is in a loop for now, but it seems to encounter the issue pretty quickly on my side (less than 30 iterations, sometimes even the 2nd iteration is throwing) :

var s3config = new AmazonS3Config() { ServiceURL = "__S3URL__", ForcePathStyle = true };
var s3Client = new AmazonS3Client(accessKeyId, accessSecretKey, s3config);
string bucketName = "__BUCKETNAME__";

for (int i = 0; i < 1000; i++)
{
    try
    {
        Console.WriteLine($"Index : {i} started at {DateTime.Now.ToString("HH:mm.ss")}");

        using (var stream = new FileStream("bigFile.xml", FileMode.Open))
            await UploadAsync(s3Client, bucketName, storageName, stream);

        Console.WriteLine($"S3 put. Start reading stream to copy at {DateTime.Now.ToString("HH:mm.ss")}");

        using (var ms = new MemoryStream())
        using (var inStream = await GetStreamAsync(s3Client, bucketName, storageName))
            await inStream.CopyToAsync(ms);

        Console.WriteLine($"Stream retrieved at {DateTime.Now.ToString("HH:mm.ss")}");
        await s3Client.DeleteObjectAsync(bucketName, storageName);
        Console.WriteLine($"Index : {i} ended at {DateTime.Now.ToString("HH:mm.ss")}");
    }
    catch (Exception)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine($"Failed at {DateTime.Now.ToString("HH:mm.ss")}");
        Console.ResetColor();
        throw;
    }
}

Possible Solution

No response

Additional Information/Context

Only having the issue with big files, the test provided was run with a 220Mb file. Having the issue with a 50Mb file too.

AWS .NET SDK and/or Package version used

AWSSDK.S3 v3.7.405.7

Targeted .NET Platform

.NET 8

Operating System and version

Windows 11

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThis issue is a bug.p3This is a minor priority issueresponse-requestedWaiting on additional info and feedback. Will move to "closing-soon" in 7 days.s3

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions