Skip to content

NullReferenceException when calling AddPartETags on CompleteMultipartUploadRequest object #3815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1 task done
teian opened this issue May 15, 2025 · 2 comments
Open
1 task done
Assignees
Labels
bug This issue is a bug. needs-review p2 This is a standard priority issue s3

Comments

@teian
Copy link

teian commented May 15, 2025

Describe the bug

Hi,

I encountered a NullReferenceException when trying to call AddPartETags on the CompleteMultipartUploadRequest. It seems the AddPartETags params overload function is checking if the partETags property is null but it is not creating the List like the other overloads resulting in the exception.

Regression Issue

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

Expected Behavior

No NullReferenceException when adding PartETag via AddPartETags(param[] PartETag etags)

Current Behavior

Completing the request results in a NullReferenceException since the partETags property is null

Reproduction Steps

  • Initialize a new Multipart Upload
  • Upload parts
  • Create CompleteMultipartUploadRequest and add PartETag via AddPartETags(param[] PartETag etags) overload
  • call CompleteMultipartUploadAsync

Possible Solution

Ensure that partETags property is correctly initialized for all AddPartETags overloads

Additional Information/Context

No response

AWS .NET SDK and/or Package version used

AWSSDK.S3 4.0.0.3

Targeted .NET Platform

.NET 9

Operating System and version

Ubuntu

@teian teian added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels May 15, 2025
@github-actions github-actions bot added the potential-regression Marking this issue as a potential regression to be checked by team member label May 15, 2025
@ashishdhingra ashishdhingra self-assigned this May 15, 2025
@ashishdhingra ashishdhingra added needs-reproduction This issue needs reproduction. s3 p2 This is a standard priority issue and removed needs-triage This issue or PR still needs to be triaged. labels May 15, 2025
@ashishdhingra
Copy link
Contributor

ashishdhingra commented May 15, 2025

Reproducible (using V4) using below code (taken from Uploading an object using multipart upload):

using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.SimpleEmailV2;

const string bucketName = "<<bucket-name>>";
const string keyName = "<<uploaded-file-key-name>>";
const string filePath = "<<file-path>>";
RegionEndpoint bucketRegion = RegionEndpoint.USEast2;
IAmazonS3 s3Client = new AmazonS3Client(bucketRegion);
Console.WriteLine("Uploading an object");
UploadObjectAsync().Wait();

async Task UploadObjectAsync()
{
    // Create list to store upload part responses.
    List<UploadPartResponse> uploadResponses = new List<UploadPartResponse>();

    // Setup information required to initiate the multipart upload.
    InitiateMultipartUploadRequest initiateRequest = new InitiateMultipartUploadRequest
    {
        BucketName = bucketName,
        Key = keyName
    };

    // Initiate the upload.
    InitiateMultipartUploadResponse initResponse =
        await s3Client.InitiateMultipartUploadAsync(initiateRequest);

    // Upload parts.
    long contentLength = new FileInfo(filePath).Length;
    long partSize = 5 * (long)Math.Pow(2, 20); // 5 MB

    try
    {
        Console.WriteLine("Uploading parts");

        long filePosition = 0;
        for (int i = 1; filePosition < contentLength; i++)
        {
            UploadPartRequest uploadRequest = new UploadPartRequest
            {
                BucketName = bucketName,
                Key = keyName,
                UploadId = initResponse.UploadId,
                PartNumber = i,
                PartSize = partSize,
                FilePosition = filePosition,
                FilePath = filePath
            };

            // Track upload progress.
            uploadRequest.StreamTransferProgress +=
                new EventHandler<StreamTransferProgressArgs>(UploadPartProgressEventCallback);

            // Upload a part and add the response to our list.
            uploadResponses.Add(await s3Client.UploadPartAsync(uploadRequest));

            filePosition += partSize;
        }

        // Setup to complete the upload.
        CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest
        {
            BucketName = bucketName,
            Key = keyName,
            UploadId = initResponse.UploadId
        };
        completeRequest.AddPartETags(uploadResponses.Select(r => new PartETag(r)));

        // Complete the upload.
        CompleteMultipartUploadResponse completeUploadResponse =
            await s3Client.CompleteMultipartUploadAsync(completeRequest);
    }
    catch (Exception exception)
    {
        Console.WriteLine("An AmazonS3Exception was thrown: { 0}", exception.Message);

        // Abort the upload.
        AbortMultipartUploadRequest abortMPURequest = new AbortMultipartUploadRequest
        {
            BucketName = bucketName,
            Key = keyName,
            UploadId = initResponse.UploadId
        };
        await s3Client.AbortMultipartUploadAsync(abortMPURequest);
    }
}

Root Cause:

if (PartETags == null)
{
    PartETags = new List<PartETag>();
}

So the fix looks something like below (tested):

        /// <summary>
        /// Adds a collection of parts (including ETags and checksums) to this request.
        /// </summary>
        /// <param name="partETags">PartETags that will added to this request.</param>
        public void AddPartETags(params PartETag[] partETags)
        {
            if (PartETags == null)
            {
                PartETags = new List<PartETag>();
            }

            if (partETags != null)
            {
                foreach (PartETag part in partETags)
                {
                    this.PartETags.Add(part);
                }
            }
        }

        /// <summary>
        /// Adds a collection of parts (including ETags and checksums) to this request.
        /// </summary>
        /// <param name="partETags">PartETags that will added to this request.</param>
        public void AddPartETags(IEnumerable<PartETag> partETags)
        {
            if (PartETags == null)
            {
                PartETags = new List<PartETag>();
            }

            if (partETags != null)
            {
                foreach (PartETag part in partETags)
                {
                    this.PartETags.Add(part);
                }
            }
        }

This is possibly issue with both V3 and V4 versions.

@ashishdhingra ashishdhingra added needs-review and removed needs-reproduction This issue needs reproduction. potential-regression Marking this issue as a potential regression to be checked by team member labels May 15, 2025
@teian
Copy link
Author

teian commented May 15, 2025

@ashishdhingra V3 works. Issue popped up when updating to the V4 Package but it might be a good idea to also investigate there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. needs-review p2 This is a standard priority issue s3
Projects
None yet
Development

No branches or pull requests

2 participants