Skip to content

How do I resolve template validation or template format errors in CloudFormation?

8 minute read
0

I want to validate my AWS CloudFormation template to make sure that I don’t have syntax errors.

Resolution

Note: If you receive errors when you run AWS Command Line Interface (AWS CLI) commands, then see Troubleshooting errors for the AWS CLI. Also, make sure that you're using the most recent AWS CLI version.

Complete the following tasks based on the error message that you receive.

"JSON not well-formed" or "YAML not well-formed" error

If you didn't correctly format your CloudFormation template, then you receive one of the following error messages:

"JSON not well-formed"

"YAML not well-formed"

Make sure to follow JSON or YAML syntax best practices in your CloudFormation template. To resolve this error, take the following actions:

  • Create your stack with Infrastructure Composer.
  • Validate your JSON and YAML syntax with the validate-template AWS CLI command.
  • To validate your JSON or YAML templates with the AWS CloudFormation linter, see cfn-lint on the GitHub website.

"Unresolved resource dependencies [XXXXXXXX] in the Resources block of the template" error

If your CloudFormation template doesn't specify a resource logical ID or a parameter, then you receive the following error message:

"Unresolved resource dependencies [test] in the Resources block of the template.".

To resolve this error, specify a resource logical ID. Or, create a parameter named test where the reference returns the ImageId value. The following example JSON and YAML templates include a parameter with test as the name and ImageId as the value.

Example JSON:

{
  "Parameters": {
     "test": {
         "Type": "String",
         "Default": "ami-xxx"
       }
  },
  "Resources" : {
    "EC2Instance01" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : {"Ref": "test"}
      }
    }
  }
}

Example YAML:

Parameters:
  test:
    Type: String
    Default: ami-xxx
Resources:
  EC2Instance01:
    Type: 'AWS::EC2::Instance'
    Properties:
      ImageId: !Ref test

"Unrecognized parameter type: XXXXXXXX" or "Invalid template parameter property 'XXXXXXXX'" error

If your JSON and YAML templates include the default value for ParameterC as the intrinsic function Fn::Sub, then you receive the following error message:

"Every Default member must be a string."

Parameters don't support intrinsic functions. Use the Fn::Sub function to specify ParameterA and ParameterB values. To resolve this error, remove ParameterC.

To remove ParameterC in your CloudFormation template, complete the following steps:

  1. Set Type to one of the following supported properties, String, Number, List, or CommaDelimitedList.
  2. Verify that the parameters include only the permitted properties.
  3. Confirm that the Parameters section doesn't contain any intrinsic functions.

Example JSON:

{
  "Parameters": {
    "ParameterA": {
      "Type": "String",
      "Default": "abc"
    },
    "ParameterB": {
      "Type": "String",
      "Default": "def"
    }
  },
  "Resources": {
    "MyS3Bucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "BucketName": {
          "Fn::Sub": "${ParameterA}-${ParameterB}"
        }
      }
    }
  }
}

Example YAML:

Parameters:
 ParameterA:
  Type: String
  Default: abc
 ParameterB:
  Type: String
  Default: def
Resources:
 MyS3Bucket:
  Type: 'AWS::S3::Bucket'
  Properties:
   BucketName: !Sub ${ParameterA}-${ParameterB}

"Every Condition member must be a string" error

Your JSON and YAML templates might specify the condition in the resource EC2RouteA as a list of strings instead of a single string. If so, then you receive the following error message:

"Every Condition member must be a string."

To resolve this error, add ConditionAandB to the Conditions section of your template. Then, use ConditionAandB as the condition for the EC2RouteA resource.

Example JSON:

{
  "Conditions": {
    "ConditionA": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            "",
            "Sample"
          ]
        }
      ]
    },
    "ConditionB": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            "",
            "Sample"
          ]
        }
      ]
    },
    "ConditionAandB": {
      "Fn::And": [
        {
          "Condition": "ConditionA"
        },
        {
          "Condition": "ConditionB"
        }
      ]
    }
  },
  "Resources": {
    "EC2RouteA": {
      "Type": "AWS::EC2::Route",
      "Condition": "ConditionAandB",
      "Properties": {
        ...
      }
    }
  }
}

Example YAML:

Conditions:
  ConditionA:
    Fn::Not:
    - Fn::Equals:
      - ''
      - Sample
  ConditionB:
    Fn::Not:
    - Fn::Equals:
      - ''
      - Sample
  ConditionAandB:
    Fn::And:
    - Condition: ConditionA
    - Condition: ConditionB
Resources:
  EC2RouteA:
    Type: AWS::EC2::Route
    Condition: ConditionAandB
    Properties:

"Unrecognized resource types: [XXXXXXXX]" error

Not every resource type is available in every AWS Region. If your template includes resource types that aren't available in your Region, then you receive the following error message:

"Unrecognized resource types: [XXXXXXXX]."

To resolve this error, verify that your resource is available in your Region. If your template consists of any serverless resources, then include a Transform declaration.

Example JSON:

{
    "Transform": "AWS::Serverless-2016-10-31", #Make sure to include this.
    "Resources": {
        "MyServerlessFunctionLogicalID": {
            "Type": "AWS::Serverless::Function",
            "Properties": {
                "Handler": "index.handler",
                "Runtime": "nodejs8.10",
                "CodeUri": "s3://testBucket/mySourceCode.zip"
            }
        }
   }
}

Example YAML:

Transform: AWS::Serverless-2016-10-31 #Make sure to include this.
Resources:
  MyServerlessFunctionLogicalID:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs8.10
      CodeUri: 's3://testBucket/mySourceCode.zip'

"The [environmental resource] 'XXXXXXXX' does not exist" error

If the AWS::EC2::Instance resource in your stack specifies a security group, then you receive the following error message:

"The sg-1234567890 does not exist."

The stack fails if the security group doesn't exist or the security group doesn't exist in the stack's Region. To resolve this error, add the SecurityGroupIDs to your template.

LinuxInstance:
    Type: AWS::EC2::Instance
    Properties:
      SubnetId: !Ref ServerSubnetID 
      KeyName: !Ref EC2KeyPairName
      SecurityGroupIds: sg-1234567890 #<This resource must exist and be in the same AWS Region as the stack.>

If you hardcode a resource or Amazon Resource Name (ARN) into one of your stack's resources for one that's outside of the CloudFormation stack, then verify the following:

  • The resource name or ARN is correct.
  • The resource exists.
  • The resource exists in the same Region as the stack. Some resources accept properties across Regions or accounts.

"Invalid template property or properties [XXXXXXXX]" error

If you set the bucket resource on the same level as the Resources section in your JSON and YAML templates, then you receive the following error message:

"Template validation error: Invalid template property or properties [Bucket]."

This error occurs when the CloudFormation template validator identifies the bucket resource as a section-level specification. A section-level specification isn't allowed as a template property. It's a best practice to use only permitted template properties in your CloudFormation template.

To resolve this error, specify the bucket resource inside the Resources section.

Example JSON:

{
  "Resources": {
    "WaitCondition": {
      "Type": "AWS::CloudFormation::WaitCondition"
    },
    "Bucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "Name": "BucketName"
      }
    }
  }
}

Note: Replace BucketName with your bucket name.

Example YAML:

Resources:
  WaitCondition:
    Type: 'AWS::CloudFormation::WaitCondition'
  Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      Name: BucketName

Note: Replace BucketName with your bucket name.

"Invalid policy syntax" or "MalformedPolicy" error

When you create an identity policy, resource policy, service control policy, or resource control policy, the validation is split into two steps. These steps include AWS Identity and Access Management (IAM) validation and CloudFormation validation.

To validate the policy, create your policy, and then run the following validate-policy AWS CLI command:

➜  aws accessanalyzer validate-policy --policy-document file://policy-document.json --policy-type IDENTITY_POLICY

Note: Replace policy-document.json with the file path to your JSON file.

If you run the validate-policy AWS CLI command, then you receive the "Invalid policy syntax" or "MalformedPolicy" error message. To resolve this issue, change the Action to s3:DeleteObject and run the command again.

Example JSON:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyObjectDeletionForAllExceptRolePrefix",
      "Effect": "Deny",
      "Action": [
        "s3:DeleteObject",
        "s3:DeleteObjectVersion",
        "s3:PutLifecycleConfiguration"
      ],
      "Resource": ["arn:aws:s3:::BUCKET_NAME/*"]
    }
  ]
}

Note: Replace BUCKET_NAME with your bucket name.

Add the validated policy to your CloudFormation template and specify parameters or resources.

If the sub function references a parameter that isn't present in the template, then you receive the following error message:

"An error occurred (ValidationError) when calling the ValidateTemplate operation: Template format error: Unresolved resource dependencies [Bucket] in the Resources block of the template"

To resolve this error, update the Resource to arn:aws:s3:::${BucketName}/* in the template.

Example JSON:

{
  "Parameters": {
    "BucketName": {
      "Type": "String"
    },
    "RoleName": {
      "Type": "String"
    }
  },
  "Resources": {
    "ManagedPolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "Roles": [
          {
            "Ref": "RoleName"
          }
        ],
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "DenyObjectDeletionForAllExceptRolePrefix",
              "Effect": "Deny",
              "Action": [
                "s3:DeleteObject",
                "s3:DeleteObjectVersion",
                "s3:PutLifecycleConfiguration"
              ],
              "Resource": [
                {
                  "Fn::Sub": "arn:aws:s3:::${BucketName}/*"
                }
              ]
            }
          ]
        }
      }
    }
  }
}

Note: Replace BucketName with your bucket name.

Manually verify the policy syntax for IAM policy-related resources

To manually verify that the policy is valid, use the following policy template:

{  
    "Resources": {  
        "Policy": {  
            "Type": "AWS::IAM::Policy",  
            "Properties": {  
                "PolicyName": "IamPolicyName",  
                "PolicyDocument": {  
                    "Version": "2012-10-17",  
                    "Statement": [  
                        {  
                            "Effect": "effect",  
                            "Action": [  
                                "service:API_action",  
                                "<...>"  
                            ],  
                            "Resource": "desiredResourceARN",  
                            "Condition": {  
                                "ConditionConfiguration": {  
                                    "conditionKey": [  
                                        "values"  
                                    ]  
                                },  
                                "ConditionConfiguration2": "<...>"  
                            }  
                        }  
                    ]  
                }  
            }  
        }  
    }  
}

Note: Replace service with your service name, and API_action with your API action for your selected service. For more information, see IAM JSON policy element reference.

Integrate your JSON policy document with a YAML format template

If you integrate a JSON policy document with a YAML format template for provisioning CloudFormation, then you can change how the document appears in the template. This avoids YAML and JSON mixed blocks. After integration, the policy elements look similar to the following example template:

Resources:  
  Policy:  
    Type: 'AWS::IAM::Policy'  
    Properties:  
      PolicyName: IamPolicyName  
      PolicyDocument:  
        Version: 2012-10-17  
        Statement:  
          - Effect: effect  
            Action:  
              - '<service>:<API_action>'  
              - <...>  
            Resource: desiredResourceARN  
            Condition:  
              ConditionConfiguration:  
                conditionKey:  
                  - values  
              ConditionConfiguration2: <...>

Note: Replace IamPolicyName with your IAM policy name.