CloudFormation Gotcha: Numbers Are Strings

Good day!

CloudFormation templates take parameters. There are several types. One of those types is Number. Here’s a super-simple demo template:

---
AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  CoolNumber:
    Type: Number

Resources:
  CoolResource:
    Type: AWS::SSM::Parameter
    Properties:
      Name: CoolNumber
      Type: String
      Value: !Ref CoolNumber

It just passes the CF param into an SSM param. It’s a little funky that we can create an SSM param with type String from a CF param with type Number, but in CF all numbers become strings when you Ref them (see the link above). That’s weird but it doesn’t break anything. Things break when we try to create a stack from the template.

Here’s a params file. We set our number to an integer:

[
  {
    "ParameterKey": "CoolNumber",
    "ParameterValue": 1
  }
]

If we try to launch the template, it fails:

aws cloudformation create-stack \
  --template-body file://./cool_stack.yaml \
  --stack-name CoolStack \
  --parameters file://./params.json

Parameter validation failed:
Invalid type for parameter Parameters[0].ParameterValue, value: 1, type: <class 'int'>, valid types: <class 'str'>

But we declared a number! We gave it a number! Why does it want a string? 😡

In CloudFormation, parameter types aren’t really types. They’re validators. CF expects to receive everything as a string, then it checks to see if that string looks like the parameter’s “type”. In our example, it wants a string that happens to contain characters that represent a number.

This works (the only difference is the new quote marks):

[
  {
    "ParameterKey": "CoolNumber",
    "ParameterValue": "1"
  }
]

(╯°□°)╯︵ ┻━┻

I’ve also seen this behavior from CI/CD pipelines that use SDK-driven plugins to launch stacks with params files.

There are cases where you won’t get this error. I think some input mechanisms end up converting values to strings for you.

  • Text box in the console works:
    console_number_param.png
  • Inline params in CF’s CLI commands in bash work:
    aws cloudformation deploy \
      --template-file cool_stack.yaml \
      --stack-name CoolStack \
      --parameter-overrides CoolNumber=1
    
    aws cloudformation create-stack \
      --template-body file://./cool_stack.yaml \
      --stack-name CoolStack \
      --parameters ParameterKey=CoolNumber,ParameterValue=1
    

Specifically in CloudFormation, here’s what you should do: declare whatever parameter types you need, but always pass the values in a strings. Anywhere else I can think of that would cause an error. Only do this for CloudFormation.

Keep your automation weird!

Adam

If this was helpful and you want to save time by getting “copy and paste” patterns for Cloud DevOps in your inbox, subscribe here. If you don’t want to wait for the next one, check out these: