Container_definitions is invalid: Error decoding JSON: invalid character 'c'

Hi, I am facing issue with container definition.

data "template_file" "env_vars" {
  template = file("env_vars.json")
}
resource "aws_ecs_task_definition" "test" {
  family                   = "test"
  container_definitions    = <<DEFINITION
  [
    {
      "name"             : "test",
      "image"            : "image",
      cpu                : 1,
      "memory"           : 2048,
      "entrypoint"       : ["bash", "-c"],
      "command"          : ["/bin/bash -c '/opt/run-master.sh'"],
      "workingDirectory" : "/opt/airflow",
      "essential"        : true,
      "environment"      : ${data.template_file.env_vars.rendered},

      "portMappings" : [
        {
          "containerPort" : 8080,
          "hostPort"      : 8080
        },
        {
          "containerPort" : 5555,
          "hostPort" : 5555
        }
      ],
    },
    {
      "name"       : "rabbitmq",
      "image"      : "image",
      "entrypoint" : ["bash", "-c"],
      "command"    : ["bash -c '/run/run.sh'"],
      "memory"     : 1024,
      "essential"  : true,
      "cpu"        : 1,
      "portMappings" : [
        {
          "containerPort" : 5672,
          "hostPort" : 5672
        },
        {
          "containerPort" : 15672
          "hostPort" : 15672
        }
      ],
    }
    ]
    DEFINITION

during terraform plan

│ Error: ECS Task Definition container_definitions is invalid: Error decoding JSON: invalid character 'c' looking for beginning of object key string

Unable figure out the issue.

Hi rahul1436,
try to put inside double quotes also the first field “cpu”

Hi @rahul1436,

Problems like this are why we recommend using jsonencode to construct JSON strings, rather than string concatenation via templates. That way the function can ensure that the result will be valid JSON syntax, and you’ll only need to worry about making sure the data structure is an appropriate shape to be accepted by the remote system.

In this case I would rewrite like the following, so that the data structure to be encoded can be written using Terraform’s own expression syntax, and then jsonencode will convert it to JSON:

  container_definitions = jsonencode([
    {
      name             = "test"
      image            = "image"
      cpu              = 1
      memory           = 2048
      entrypoint       = ["bash", "-c"]
      command          = ["/bin/bash -c '/opt/run-master.sh'"]
      workingDirectory = "/opt/airflow"
      essential        = true
      environment      = jsondecode(file("${path.module}/env_vars.json"))

      portMappings = [
        {
          containerPort = 8080
          hostPort      = 8080
        },
        {
          containerPort = 5555
          hostPort      = 5555
        },
      ]
    },
    # (and then similar for your other element)
  ])

Because your environment variables are in separate file that is itself JSON encoded, the environment expression here will load that file and JSON decode it in order to insert that data structure into the outer one and thus avoid incorrect quoting. This should therefore produce a similar result to your technique, but with the valid JSON syntax generated by Terraform itself.

1 Like