How to fix Error: Dynamic blocks may not be nested within dynamic blocks in Terraform

TerraformINTERMEDIATEMEDIUMUpdated Dec 30, 2025· 138 views

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.

Quick fix

Fixes Error: Dynamic blocks may not be nested within dynamic blocks

# ❌ 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
    }
  }
}
  1. Flatten your data structure using locals
  2. Use setproduct for Cartesian products
  3. Use iterator argument in single dynamic block
  4. Move iteration logic to a module
terraform — error
# ❌ 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
}
}
}
Error: Dynamic blocks may not be nested within dynamic blocks

What this error means

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.

Typical symptoms

  • Error message states 'Dynamic blocks may not be nested within dynamic blocks'
  • Configuration fails during terraform validate or terraform plan
  • Attempting to use dynamic block inside another dynamic block's content
  • Complex nested resource configurations with multiple levels of iteration
  • Trying to dynamically create nested provider or provisioner blocks

Common causes

  1. Directly nesting a dynamic block inside the content of another dynamic block
  2. Attempting to generate dynamic blocks themselves instead of their content
  3. Misunderstanding the difference between dynamic block content and dynamic block declarations
  4. Complex data structures requiring multiple levels of iteration
  5. Trying to use dynamic blocks for provider or provisioner configuration with nested iteration

How to fix "Error: Dynamic blocks may not be nested within dynamic blocks"

1Flatten your data structure using locals

Instead of nesting dynamic blocks, flatten your data into a single iterable collection using locals and built-in functions:

hcl
# ❌ 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
    }
  }
}
2Use setproduct for Cartesian products

When you need combinations of multiple iterables, use the setproduct function to generate all combinations:

hcl
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
}
3Use iterator argument in single dynamic block

You can still have a single dynamic block that generates nested block content by using the iterator argument to avoid name conflicts:

hcl
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
      }
    }
  }
}
4Move iteration logic to a module

Separate your configuration into modules where each module handles one level of iteration:

hcl
# 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
}
5Use for_each with a flattened map

Convert nested structures to a map and use for_each instead of dynamic blocks:

hcl
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
}

Advanced notes

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.

Frequently asked questions

What does "Error: Dynamic blocks may not be nested within dynamic blocks" mean?
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.
How do I fix "Error: Dynamic blocks may not be nested within dynamic blocks"?
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.
What causes "Error: Dynamic blocks may not be nested within dynamic blocks"?
Directly nesting a dynamic block inside the content of another dynamic block Attempting to generate dynamic blocks themselves instead of their content Misunderstanding the difference between dynamic block content and dynamic block declarations
Is the "Error: Dynamic blocks may not be nested within dynamic blocks" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading