Skip to content
Latchkey

Terraform "dynamic" Block Errors in CI

A dynamic {} block generates repeated nested blocks from a collection. It errors when for_each is not iterable, the iterator name is referenced wrong, or it tries to generate a block the schema does not allow.

What this error means

plan fails inside a dynamic block - for_each is null or not a collection, <iterator>.value references the wrong name, or the generated nested block is not supported by the resource schema.

terraform output
Error: Invalid dynamic for_each value

  on sg.tf line 8, in resource "aws_security_group" "web":
   8:     for_each = var.ingress_rules

Cannot use a null value in for_each. Replace this with an empty map or set to
generate no blocks.

Common causes

for_each is null or not a collection

A dynamic block’s for_each must be a map or set. A null variable, or a single object instead of a collection, makes iteration fail.

Wrong iterator reference

Inside the block you reference <label>.value. By default the iterator is named after the block; a custom iterator = x changes it to x.value. Mixing these up breaks the reference.

Generating an unsupported nested block

A dynamic block can only generate nested blocks the resource schema actually accepts; targeting a non-block argument fails.

How to fix it

Iterate a non-null collection and reference the iterator correctly

Default the collection to empty and reference the block label’s .value.

sg.tf
resource "aws_security_group" "web" {
  dynamic "ingress" {
    for_each = var.ingress_rules == null ? {} : var.ingress_rules
    content {
      from_port = ingress.value.from
      to_port   = ingress.value.to
      protocol  = ingress.value.protocol
    }
  }
}

Match the generated block to the schema

  1. Confirm the nested block name (e.g. ingress) is a real block on the resource.
  2. Use content {} to define each generated block’s arguments.
  3. If you set a custom iterator, reference that name, not the label.

How to prevent it

  • Default dynamic for_each collections to empty, never null.
  • Reference the iterator by the block label (or your custom iterator name).
  • Only generate nested blocks the resource schema supports.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →