A local value in Terraform is referencing itself, either directly or through a chain of other locals. Terraform cannot evaluate self-referential or circular dependency chains. This error is resolved by breaking the circular reference and restructuring your locals so dependencies flow in one direction.
Terraform evaluates all locals in a block simultaneously. If a local value references itself (directly like `local.x = local.x + 1`) or indirectly through other locals (like `local.a = local.b` and `local.b = local.a`), Terraform cannot determine the order of evaluation. This creates an infinite loop or circular dependency that Terraform must reject to prevent execution failure.
Read the error message carefully. Terraform will indicate which local value has the circular reference. For example:
Error: Self-referential local value
on main.tf line 5, in locals:
5: my_value = local.my_value + 1
A local value cannot reference itself. Restructure your configuration to break the cycle.Note the local name and the line number.
If a local references itself directly, use a static value or input variable as the base:
Incorrect (causes error):
locals {
my_value = local.my_value + 1 # ERROR: references itself
}Correct approach:
locals {
base_value = 1 # Start with a static value
my_value = local.base_value + 1 # Reference the base
}Or use a variable:
variable "starting_value" {
default = 1
}
locals {
my_value = var.starting_value + 1
}If two or more locals reference each other in a circle, restructure so each local only references locals defined earlier:
Incorrect (causes error):
locals {
value_a = local.value_b + 1 # ERROR: depends on value_b
value_b = local.value_a + 1 # which depends back on value_a
}Correct approach:
locals {
base_value = 1 # Independent base
value_a = local.base_value + 1 # Depends only on base
value_b = local.value_a + 1 # Depends only on value_a (forward dependency)
}The key principle: locals must have one-way dependencies, not cycles.
For complex configurations, split your locals into multiple blocks to make dependencies clearer:
locals {
environment = "prod"
region = "us-east-1"
}
locals {
# These depend on the first block
app_name = "${local.environment}-app"
resource_prefix = "${local.environment}-${local.region}"
}
locals {
# These depend on the second block
full_name = "${local.resource_prefix}-${local.app_name}"
}Multiple blocks are evaluated sequentially, so later blocks can safely reference earlier ones without creating cycles.
If you're trying to incrementally build a map or list using merge() or concat(), split it into separate locals:
Incorrect (causes error):
locals {
my_map = merge(local.my_map, { new_key = "value" }) # ERROR: references itself
}Correct approach:
locals {
base_map = {
existing_key = "value"
}
extended_map = merge(local.base_map, {
new_key = "value"
})
}Or use multiple stages:
locals {
map_v1 = { key1 = "value1" }
map_v2 = merge(local.map_v1, { key2 = "value2" })
final_map = merge(local.map_v2, { key3 = "value3" })
}For list or map transformations, use for expressions instead of trying to reference the local being defined:
Incorrect (might cause error):
locals {
items = [for item in local.items : upper(item)] # ERROR: references itself
}Correct approach:
locals {
raw_items = ["apple", "banana", "cherry"]
upper_items = [for item in local.raw_items : upper(item)]
}After restructuring your locals, run Terraform plan to verify the error is resolved:
terraform planIf the error persists, check that:
1. You're not using local. to reference the value being defined
2. All dependencies flow in one direction (no cycles)
3. You've saved the configuration file after editing
If you're still seeing issues, run:
terraform validateto get detailed feedback on the problematic locals.
Understanding Locals Evaluation: Terraform evaluates all locals in a single block simultaneously (not sequentially). This is why local a cannot reference local b and local b reference local a - they're evaluated at the same time, so there's no 'first' value to reference.
Multiple Locals Blocks: You can define multiple locals blocks in the same file. They are evaluated in order from top to bottom, so a later block can reference a local from an earlier block. This is a useful pattern for organizing complex configurations.
Dynamic Blocks vs Locals: If you're trying to dynamically generate resources based on locals, be careful not to create self-references. Use for_each over a static local list, not a local that references itself.
Root Module vs Modules: This error applies to locals in any context - root module, child modules, or nested blocks. The solution is the same: break the circular reference.
Terraform Version Compatibility: This validation has been consistent across Terraform versions. All versions reject self-referential locals.
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