This error occurs when you try to use Terraform template directives (like %{for}, %{if}) inside a dynamic block. Dynamic blocks use their own for_each iteration mechanism and don't support template syntax. The fix is to remove template directives and use dynamic block expressions instead.
Terraform has two separate mechanisms for iteration and conditional logic: dynamic blocks and template directives. Dynamic blocks (using for_each) generate nested configuration blocks, while template directives (%{for}, %{if}) work inside string templates (heredocs and quoted strings). These two systems cannot be mixed. When you try to include template directives inside a dynamic block's content, Terraform rejects them because dynamic blocks process their iteration at a different stage of configuration parsing than template expressions. The dynamic block's for_each and iterator are the proper way to handle repetition within resource configuration.
Look for the error message line number and examine your dynamic block for any %{ syntax:
# WRONG - Template directive in dynamic block
dynamic "ingress" {
for_each = var.rules
content {
description = "%{ if ingress.value.add_desc }Custom rule%{ endif }"
}
}The %{ if } and %{ endif } are template directives and are not allowed here.
Use Terraform's native conditional operator (condition ? true_val : false_val) inside the dynamic block's content:
# CORRECT - Use conditional expression
dynamic "ingress" {
for_each = var.rules
content {
description = ingress.value.add_desc ? "Custom rule" : ""
}
}This achieves the same result without template directives.
If you need to process or transform data before using it in the dynamic block, use Terraform functions like map(), filter(), or list comprehension within the for_each argument itself:
# Transform data before dynamic block processes it
dynamic "ingress" {
for_each = [for rule in var.rules : rule if rule.enabled]
content {
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
}
}This keeps all iteration logic in the dynamic block where it belongs.
After making changes, validate your configuration to ensure no errors remain:
terraform validateThis will confirm that your dynamic block syntax is correct and that template directives have been properly removed or replaced with conditional expressions.
Template directives are specifically designed for string template processing and work best in heredocs and regular string interpolations. Dynamic blocks are meant for resource configuration generation and have their own expression evaluation rules.
If you need complex templating logic, consider using local values or temporary variables to pre-process your data before passing it to a dynamic block. This keeps your code cleaner and avoids mixing iteration mechanisms.
Related Terraform features: locals, for expressions (list/map comprehensions), conditional operators, and function transformations like map() and flatten() can all help you achieve complex logic without template directives in dynamic blocks.
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