Search code examples
c#amazon-s3minio

MinIO API responded with message Data read 0 is shorter than the size of input buffer


Directly putting objects from user input (MemoryStream) to an S3 object storage using Min.IO can cause a wired error of Exception has occurred: CLR/Minio.Exceptions.UnexpectedShortReadException Exception thrown: 'Minio.Exceptions.UnexpectedShortReadException' in System.Private.CoreLib.dll: 'MinIO API responded with message=Data read 0 is shorter than the size x of input buffer.'

        public async Task UploadFileAsync(IFormFile image)
        {
            using (var ms = new MemoryStream())
            {
                image.CopyTo(ms);
                var args = new Minio.DataModel.Args.PutObjectArgs { }
                        .WithBucket(bucket)
                        .WithObject("test-" + Guid.NewGuid().ToString())
                        .WithContentType(image.ContentType)
                        .WithStreamData(ms)
                        .WithObjectSize(ms.Length);
                await minioClient.PutObjectAsync(args);
            }
        }

Solution

  • The function CopyTo will increase the Position (which is a pointer) of a MemoryStream, regarding to the source code of MinIO, it will not reset the MemoryStream instance's pointers (which is somehow a good decision if there are multiple files stored in a MemoryStream and someone wants to break it in chunks.

    This is their condition for the exception:

    var bytes = await ReadFullAsync(args.ObjectStreamData, (int)args.ObjectSize).ConfigureAwait(false);
    var bytesRead = bytes.Length;
    if (bytesRead != (int)args.ObjectSize)
    // ----------> This is the place exception accrues.
    

    To solve the issue, we have to reset the pointer on our own before passing it to MinIO Client SDK.

    The ANSWER would be simply adding the line below AFTER CopyTo:

    ms.Position = 0;
    

    Hope it saves your time.