Terraform does not support nesting dynamic blocks directly inside other dynamic blocks. This limitation prevents you from using a dynamic block to generate nested dynamic blocks. You must use data structure flattening or other approaches to work around this constraint.
Terraform's configuration language has a fundamental limitation: you cannot place one dynamic block directly inside another dynamic block. While dynamic blocks are powerful for generating resource arguments and nested blocks, they cannot be used to generate other dynamic blocks themselves. This is a language-level constraint imposed by Terraform's parser and evaluator.
Instead of nesting dynamic blocks, flatten your data into a single iterable collection using locals and built-in functions:
# ❌ Wrong - nested dynamic blocks
resource "example_resource" "parent" {
dynamic "outer" {
for_each = var.outer_items
content {
dynamic "inner" {
for_each = outer.value.inner_items
content {
name = inner.value.name
}
}
}
}
}
# ✓ Correct - flatten to single level
locals {
flattened_items = flatten([
for outer in var.outer_items : [
for inner in outer.inner_items : {
outer_key = outer.key
inner_name = inner.name
}
]
])
}
resource "example_resource" "parent" {
dynamic "item" {
for_each = local.flattened_items
content {
name = item.value.inner_name
}
}
}When you need combinations of multiple iterables, use the setproduct function to generate all combinations:
locals {
region_az_pairs = setproduct(
var.regions,
var.availability_zones
)
}
resource "example_instance" "multi_region" {
for_each = {
for pair in local.region_az_pairs : "${pair[0]}-${pair[1]}" => {
region = pair[0]
az = pair[1]
}
}
region = each.value.region
az = each.value.az
}You can still have a single dynamic block that generates nested block content by using the iterator argument to avoid name conflicts:
resource "aws_lb" "example" {
# Dynamic block for target groups
dynamic "target_group" {
for_each = var.target_groups
iterator = tg
content {
name = tg.value.name
# Nested blocks (not dynamic) that reference outer iterator
health_check {
path = tg.value.health_check.path
matcher = tg.value.health_check.matcher
}
}
}
}Separate your configuration into modules where each module handles one level of iteration:
# module/outer/main.tf - handles outer iteration
dynamic "outer_block" {
for_each = var.outer_items
content {
# Call inner module for each outer item
inner_item = module.inner[outer_block.key]
}
}
# module/inner/main.tf - handles inner iteration
resource "example_resource" "items" {
for_each = var.inner_items
name = each.value.name
}
# root/main.tf
module "inner" {
for_each = var.outer_items
source = "./module/inner"
inner_items = each.value.items
}Convert nested structures to a map and use for_each instead of dynamic blocks:
locals {
nested_map = {
for outer_key, outer_val in var.outer_config : outer_key => {
for inner_key, inner_val in outer_val.inner_config : "${outer_key}-${inner_key}" => inner_val
}
}
flattened_map = merge([
for outer_key, inner_configs in local.nested_map : inner_configs
]...)
}
resource "example_resource" "items" {
for_each = local.flattened_map
name = each.key
# ... configuration
}This limitation exists because Terraform's dynamic blocks are evaluated at the HCL level before the configuration is processed. The parser cannot determine what a nested dynamic block should generate, as it would require two-stage evaluation. If you encounter this restriction, it's often a signal to reconsider your data structure design. The flatten, setproduct, and merge functions are powerful tools for transforming nested data into single-level collections that work with a single dynamic block. When working with complex nested structures in providers like AWS (target groups, listeners, rules), consider whether the provider itself expects nested static blocks (which can be generated by a single dynamic block) or if you should use multiple resources with parent-child relationships instead.
Error: Error rendering template: template not found
How to fix "template not found" error in Terraform
Error: Error generating private key
How to fix 'Error generating private key' in Terraform
Error creating Kubernetes Service: field is immutable
How to fix "field is immutable" errors in Terraform
Error: Error creating local file: open: permission denied
How to fix "Error creating local file: permission denied" in Terraform
Error: line endings have changed from CRLF to LF
Line endings have changed from CRLF to LF in Terraform