aws-cloudformation

CloudFormation Error: Subscription Property Expects Array but Received Object


I'm encountering an issue while deploying an AWS CloudFormation stack for SNS. The error message I receive is:

Model validation failed (#/Subscription: expected type: JSONArray, found: JSONObject)

I have the following CloudFormation template snippet where I define an SNS topic and set the Subscription property. The intention is to dynamically create an array of subscriptions from a parameter that can contain email adresses.

Parameters:
  Endpoint1:
    Type: String
  Endpoint2:
    Type: String
  EnvironmentName:
    Description: "The environment name (e.g., dev, prod)"
    Type: String
Resources:
  Topic1:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: !Sub ${EnvironmentName} notification1
      TopicName: !Sub ${EnvironmentName}-notification1
      Subscription:
        Endpoint: ${Endpoint1}
        Protocol: "email"
  StuckedObjectsSNSTopic:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: !Sub ${EnvironmentName} Notification2
      TopicName: !Sub ${EnvironmentName}-notification2
      Subscription:
        Endpoint: ${Endpoint2}
        Protocol: "email"

I pass Endpoint1 and Endpoint2 in a dict from python.

ENDPOINT1 = "email1@gmail.com"
ENDPOINT2 = "email2@gmail.com"

context["Endpoint1"] = ENDPOINT1
context["Endpoint2"] = ENDPOINT2

The Subscription property is expected to be an array, but the template is giving an error indicating that it received an object instead.

How can I correctly format the Subscription property to always be a valid JSON array in CloudFormation, especially when dynamically handling both single and multiple email addresses? Is there a more reliable way to achieve this?


Solution

  • It needs to be an Array as mentioned.

    You have:

    Resources:
      Topic1:
        Type: AWS::SNS::Topic
        Properties:
          DisplayName: !Sub ${EnvironmentName} notification1
          TopicName: !Sub ${EnvironmentName}-notification1
          Subscription:
            Endpoint: ${Endpoint1}
            Protocol: "email"
    

    It needs to be:

    Resources:
      Topic1:
        Type: AWS::SNS::Topic
        Properties:
          DisplayName: !Sub ${EnvironmentName} notification1
          TopicName: !Sub ${EnvironmentName}-notification1
          Subscription:
            - Endpoint: ${Endpoint1}
              Protocol: "email"
    

    See the example in https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-topic.html#aws-resource-sns-topic--examples