Terraform for_each queue creation from YAML fails with invalid sequence

Just noticed that using for_each with a YAML variable file to provision multiple queues throws a type mismatch error.

The YAML exports a mapping, but Terraform treats it as a list during the plan phase.

Is there a specific conversion function needed to parse the YAML sequence into a valid map for for_each?

Current config snippet fails at the genesyscloud_routing_queue resource block.

This looks like a type coercion issue in Terraform rather than a Genesys Cloud API limitation. The for_each meta-argument strictly requires a map or a set of strings. When you load YAML via yamldecode(), it often returns a complex object that Terraform treats as a tuple or list if the structure isn’t perfectly flat.

You need to explicitly convert the YAML output into a map before passing it to for_each. Use toset() if you just need unique keys, or construct a map manually if you need attributes. Here is a working pattern using HCL:

locals {
 queue_map = { for k, v in yamldecode(file("queues.yaml")) : k => v }
}

resource "genesyscloud_routing_queue" "this" {
 for_each = local.queue_map
 
 name = each.value.name
 description = each.value.description
}

Warning: Ensure your YAML keys are unique and string-based. If the YAML file contains duplicate keys or non-string keys, for_each will fail validation immediately. I’ve seen this break builds when developers use numeric indices in YAML lists instead of mapping objects. Check your YAML structure first.

for_each = { for k, v in yamldecode(file("queues.yaml")) : k => v }

You might want to look at using a for-expression to explicitly convert the YAML structure into a map. for_each rejects lists or tuples, so forcing the iteration into a key-value map prevents the type mismatch error.

What’s happening here is that yamldecode() returns a generic object structure that Terraform cannot implicitly cast to a map(string, object) or set(string) required by for_each. While the for-expression suggested above works for flat lists, it fails silently or throws errors if your YAML contains nested objects or if keys contain special characters that break HCL interpolation. You must explicitly define the expected type schema to ensure the SDK-compatible resource attributes are populated correctly. Use a local variable to cast the decoded YAML into a strict map of objects. This prevents runtime type coercion errors during the apply phase and ensures that optional fields like outbound_email or wrap_up_code are handled as nullable strings rather than causing schema validation failures in the Genesys Cloud API payload.

locals {
 # Define the expected structure for each queue
 queue_schema = {
 name = string
 description = string
 enabled = bool
 skills = list(string)
 }

 # Explicitly cast yamldecode output to map of objects
 queues = {
 for k, v in yamldecode(file("${path.module}/queues.yaml")) :
 k => v if v != null
 }

 # Validate and flatten if necessary
 queue_map = {
 for k, v in local.queues :
 k => {
 name = v.name
 description = lookup(v, "description", "")
 enabled = lookup(v, "enabled", true)
 skills = lookup(v, "skills", [])
 }
 }
}

resource "genesyscloud_routing_queue" "queue" {
 for_each = local.queue_map

 name = each.value.name
 description = each.value.description
 enabled = each.value.enabled
 
 dynamic "skill" {
 for_each = each.value.skills
 content {
 name = skill.value
 }
 }
}
  • Terraform type constraints
  • Genesys Cloud Routing Queue API schema
  • HCL2 for-expressions
  • YAML decoding best practices

Have you tried mapping the YAML keys explicitly to ensure Terraform sees a strict map type?

for_each = { for k, v in yamldecode(file("queues.yaml")) : k => v if can(v.name) }

This prevents null values from breaking the plan and aligns with how I handle event payloads in Lambda.