I have a weird issue with my Terraform script. I’m trying to create multiple Genesys Cloud queues from a YAML file using for_each. The logic seems sound, but Terraform keeps throwing a resource conflict error even though the keys are unique.
Here is the YAML file queues.yaml:
queues:
sales_support:
name: Sales Support
description: First line sales
tech_support:
name: Tech Support
description: Tier 2 tech issues
And here is the HCL code:
locals {
queue_data = yamldecode(file("${path.module}/queues.yaml"))
queue_keys = keys(local.queue_data.queues)
}
resource "gen_cloud_queue" "support_queues" {
for_each = { for k, v in local.queue_data.queues : k => v }
name = each.value.name
description = each.value.description
}
When I run terraform plan, it fails with:
Error: Resource "gen_cloud_queue" "support_queues" must have a unique key for each instance. Please use distinct keys in the "for_each" expression.
I thought for k, v in ... created unique keys based on the YAML keys? I’ve tried changing the for_each to just local.queue_keys and accessing values via local.queue_data.queues[each.key], but that breaks the resource mapping. It’s driving me crazy because the keys are definitely unique strings. Anyone see what I’m missing here?
Cause: The issue likely stems from how yamldecode handles the nested structure versus what for_each expects. If you’re passing the whole decoded object into for_each, you might be getting a map of maps where the keys aren’t what you think, or Terraform is seeing a type mismatch during the plan phase. Also, Genesys Cloud queues are identified by their name in the API, but Terraform needs a unique key for its state management. If two queues have the same name but different keys in your YAML, or vice versa, you’ll get conflicts or drift.
Solution: Flatten the structure before passing it to for_each. Use yamldecode to load the file, then use for_each with the specific queue map. Make sure the keys in your YAML match the name attribute or use a distinct ID to avoid name collisions if you ever rename them.
Here’s how I structure it:
locals {
queues_data = yamldecode(file("${path.module}/queues.yaml")).queues
}
resource "gen_cloud_queue" "queue" {
for_each = local.queues_data
name = each.value.name
description = each.value.description
// Add other required attributes like wrap_up_code, etc.
}
If you’re still hitting conflicts, check if there are existing queues in Genesys Cloud with the same names that aren’t managed by Terraform. That’ll cause a state import error or a conflict. You might need to import them first or delete the manual ones. Also, make sure your queues.yaml is valid YAML. Indentation errors there can cause yamldecode to return a string instead of a map, which breaks for_each.
Run terraform plan with -debug to see exactly what keys Terraform is seeing. It usually spits out the actual map structure if there’s a type error.
resource “gen_cloud_queue” “example” {
for_each = yamldecode(file(“${path.module}/queues.yaml”))[“queues”]
name = each.value.name
description = each.value.description
}
is spot on about the map structure, but there's a subtler trap here. When you decode that YAML, the root object isn't the map of queues-it's an object containing a `queues` key. If you pass the whole decoded blob into `for_each`, Terraform sees a single map with one key (`queues`), not your individual queue definitions. You need to index into that specific key first. Also, double-check that your YAML indentation is consistent. YAML is brutal with whitespace. If `tech_support` isn't indented exactly two spaces under `queues`, it might be treated as a sibling key or ignored entirely, causing the plan to look weird. The error usually screams "conflict" because Terraform thinks it's trying to create the same resource twice or can't distinguish the keys. Just ensure `each.value` references the inner object correctly.