Skip to content

NullReferenceException on AmazonCloudFormationClient.UpdateStackAsync for SDK v4 #3824

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
greg5123334 opened this issue May 19, 2025 · 1 comment
Open
1 task done
Assignees
Labels
bug This issue is a bug. module/sdk-custom needs-review p2 This is a standard priority issue potential-regression Marking this issue as a potential regression to be checked by team member s Effort estimation: small

Comments

@greg5123334
Copy link

Describe the bug

It is a known issue when migrating from SDK v3 to v4 that Collections will return null, resulting in a NullReferenceException. The workaround is to set the static variable to pre-initialize Collectoins:

Amazon.AWSConfigs.InitializeCollections = true;

The long-term solution is to perform null-checks in code.

The problem with UpdateStackAsync however, is that the null reference is happening deep inside SDK code, not customer-facing code. The implication being, one cannot apply the fix, as it will need to be corrected in the SDK sauce itself.

Regression Issue

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

Expected Behavior

Calling UpdateStackAsync should NOT encounter NullReferenceException.

Current Behavior

Calling UpdateStackAsync DOES encounter NullReferenceException.

Reproduction Steps

using Amazon.CloudFormation;
using Amazon.CloudFormation.Model;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

// Workaround for System.NullReferenceException
// Amazon.AWSConfigs.InitializeCollections = true;

// Create a CloudFormation client with explicit region
var client = new AmazonCloudFormationClient(
    region: Amazon.RegionEndpoint.USEast1  // Change to your region
);

// Simple CloudFormation template for creating an SNS topic
string templateBody = @"{
  ""Resources"" : {
    ""MySNSTopic"" : {
      ""Type"" : ""AWS::SNS::Topic"",
      ""Properties"" : {
        ""DisplayName"" : ""MySampleTopic""
      }
    }
  },
  ""Outputs"" : {
    ""TopicARN"" : {
      ""Description"" : ""ARN of the SNS Topic"",
      ""Value"" : { ""Ref"" : ""MySNSTopic"" }
    }
  }
}";

// Choose which operation to perform
// await CreateStackAsync();
await UpdateStackAsync();

async Task CreateStackAsync()
{
    try
    {
        var response = await client.CreateStackAsync(new CreateStackRequest
        {
            StackName = "MySNSTopicStack",
            TemplateBody = templateBody,
            OnFailure = OnFailure.DELETE
        });

        Console.WriteLine($"Stack creation initiated. Stack ID: {response.StackId}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error creating stack: {ex.Message}");
    }
}

async Task UpdateStackAsync()
{
    Console.WriteLine("Starting UpdateStackAsync method...");
    try
    {
        Console.WriteLine("Preparing updated template...");
        // Updated template with a modified display name
        string updatedTemplateBody = @"{
          ""Resources"" : {
            ""MySNSTopic"" : {
              ""Type"" : ""AWS::SNS::Topic"",
              ""Properties"" : {
                ""DisplayName"" : ""MySampleTopicUpdated""
              }
            }
          },
          ""Outputs"" : {
            ""TopicARN"" : {
              ""Description"" : ""ARN of the SNS Topic"",
              ""Value"" : { ""Ref"" : ""MySNSTopic"" }
            }
          }
        }";

        Console.WriteLine("Creating UpdateStackRequest...");
        // Create a new request with minimal required parameters
        var request = new UpdateStackRequest
        {
            StackName = "MySNSTopicStack",
            TemplateBody = updatedTemplateBody
        };
        
        Console.WriteLine($"Request details: StackName={request.StackName}, Template length={request.TemplateBody?.Length ?? 0}");
        Console.WriteLine("Calling client.UpdateStackAsync...");
        
        var response = await client.UpdateStackAsync(request);
        
        Console.WriteLine("UpdateStackAsync call completed successfully");
        Console.WriteLine($"Stack update initiated. Stack ID: {response?.StackId ?? "null"}");
    }
    catch (AmazonCloudFormationException ex)
    {
        Console.WriteLine($"CloudFormation error: {ex.Message}");
        Console.WriteLine($"Error code: {ex.ErrorCode}, Request ID: {ex.RequestId}");
        Console.WriteLine($"Status code: {ex.StatusCode}");
        
        if (ex.Message.Contains("No updates are to be performed"))
        {
            Console.WriteLine("No updates needed for the stack.");
        }
    }
    catch (AmazonServiceException ex)
    {
        Console.WriteLine($"AWS Service error: {ex.Message}");
        Console.WriteLine($"Error type: {ex.ErrorType}, Error code: {ex.ErrorCode}");
        Console.WriteLine($"Request ID: {ex.RequestId}, Status code: {ex.StatusCode}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error updating stack: {ex.Message}");
        Console.WriteLine($"Error type: {ex.GetType().FullName}");
        Console.WriteLine($"Stack trace: {ex.StackTrace}");
        
        if (ex.InnerException != null)
        {
            Console.WriteLine($"Inner exception: {ex.InnerException.Message}");
            Console.WriteLine($"Inner exception type: {ex.InnerException.GetType().FullName}");
        }
    }
    Console.WriteLine("UpdateStackAsync method completed.");
}
dotnet build
dotnet run  
Hello, World!
Starting UpdateStackAsync method...
Preparing updated template...
Creating UpdateStackRequest...
Request details: StackName=MySNSTopicStack, Template length=417
Calling client.UpdateStackAsync...
Error updating stack: Object reference not set to an instance of an object.
Error type: System.NullReferenceException
Stack trace:    at Amazon.CloudFormation.Internal.ProcessRequestHandler.PreInvoke(IExecutionContext executionContext)
   at Amazon.CloudFormation.Internal.ProcessRequestHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.PipelineHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.BaseEndpointResolver.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.PipelineHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.BaseAuthResolverHandler.<>n__0[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.BaseAuthResolverHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.CallbackHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.ErrorCallbackHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Amazon.Runtime.Internal.MetricsHandler.InvokeAsync[T](IExecutionContext executionContext)
   at Program.<>c__DisplayClass0_0.<<<Main>$>g__UpdateStackAsync|1>d.MoveNext() in /home/*******/Program.cs:line 96
UpdateStackAsync method completed.

Possible Solution

No response

Additional Information/Context

No response

AWS .NET SDK and/or Package version used

AWSSDK.CloudFormation:4.0.0.4
AWSSDK.Core:4.0.0.5

Targeted .NET Platform

8.0.115

Operating System and version

Ubuntu 24.04.2 LTS

@greg5123334 greg5123334 added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels May 19, 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 19, 2025
@ashishdhingra ashishdhingra self-assigned this May 19, 2025
@ashishdhingra ashishdhingra added needs-reproduction This issue needs reproduction. module/sdk-custom and removed needs-triage This issue or PR still needs to be triaged. labels May 19, 2025
@ashishdhingra
Copy link
Contributor

ashishdhingra commented May 19, 2025

Reproducible using customer's provided code. Missing null check here.

The fix could be something like below:

...
        /// <summary>
        /// Set NotificationARNs to empty if the collection is empty before continuing on in the pipeline.
        /// </summary>
        /// <param name="executionContext"></param>
        protected virtual void PreInvoke(IExecutionContext executionContext)
        {
            var request = executionContext.RequestContext.Request;
            var updateStackRequest = request.OriginalRequest as UpdateStackRequest;
            if (updateStackRequest != null)
            {
                var arns = updateStackRequest.NotificationARNs;
                bool arnsAutoConstructed = arns is AutoConstructedList<string>;

                // if there are no NotificationARNs and the list was created by user (type is NOT AutoConstructed)
                // only then pass empty param
                if (arns.Count == 0 && !arnsAutoConstructed)
                {
                    if (request.Parameters.ContainsKey("NotificationARNs"))
                    {
                        request.Parameters["NotificationARNs"] = string.Empty;
                    }
                    else
                    {
                        request.Parameters.Add("NotificationARNs", string.Empty);
                    }
                }
            }
        }
...

@ashishdhingra ashishdhingra added p2 This is a standard priority issue needs-review s Effort estimation: small and removed needs-reproduction This issue needs reproduction. labels May 19, 2025
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. module/sdk-custom needs-review p2 This is a standard priority issue potential-regression Marking this issue as a potential regression to be checked by team member s Effort estimation: small
Projects
None yet
Development

No branches or pull requests

2 participants