The replace_triggered_by lifecycle argument is invalid because it references a variable, data source, or non-existent resource. This argument only accepts managed resource references and was introduced in Terraform 1.2.
The replace_triggered_by lifecycle meta-argument tells Terraform to replace a resource when another resource changes. It was introduced in Terraform 1.2. However, it has strict requirements about what can be referenced—only managed resources are allowed. When you try to reference local values, input variables, data sources, or non-existent resources, Terraform throws an "invalid" error because these constructs don't have the planned actions needed for replacement triggering.
The replace_triggered_by argument was introduced in Terraform 1.2. Check your version:
terraform versionIf you're using an older version, upgrade Terraform to at least 1.2:
# Using tfenv (recommended)
tfenv install 1.2.0
tfenv use 1.2.0
# Or download from https://www.terraform.io/downloadsEnsure the referenced resource exists and is a managed resource (not a variable or data source). List all resources in your configuration:
terraform state listVerify the resource name matches exactly. Common mistakes:
- Typos in resource type or name
- Using aws_instance instead of just the resource reference
- Referencing a deleted or commented-out resource
Only managed resources can be referenced. This is INVALID:
resource "aws_instance" "example" {
lifecycle {
# WRONG: referencing a variable
replace_triggered_by = [var.ami_version]
# WRONG: referencing a data source
replace_triggered_by = [data.aws_ami.latest]
# WRONG: referencing a local value
replace_triggered_by = [local.instance_config]
}
}This is CORRECT:
resource "aws_instance" "example" {
lifecycle {
# RIGHT: referencing managed resources
replace_triggered_by = [
aws_security_group.default,
aws_ami.ubuntu
]
}
}If you need to trigger replacements based on variable changes, use the terraform_data resource as an intermediary:
resource "terraform_data" "ami_version" {
input = var.ami_version
}
resource "aws_instance" "example" {
ami = data.aws_ami.latest.id
lifecycle {
replace_triggered_by = [terraform_data.ami_version]
}
}This works because terraform_data is a managed resource that Terraform tracks for planned changes.
Check for syntax errors in your resource references:
terraform validateThe output will highlight exactly which resource reference is invalid. Common syntax errors:
- Missing resource type: aws_sg instead of aws_security_group.example
- Including brackets: [aws_instance.example.id] instead of [aws_instance.example]
- Using string literals: ["aws_instance.example"] instead of [aws_instance.example]
Ensure that adding replace_triggered_by doesn't create a dependency cycle. For example, if Resource A depends on Resource B, and you make Resource B's replacement depend on Resource A, Terraform cannot resolve the order:
# BAD: Creates a cycle
resource "aws_instance" "app" {
security_groups = [aws_security_group.app.id] # A depends on B
lifecycle {
replace_triggered_by = [aws_security_group.app] # B depends on A
}
}Use terraform_data or restructure dependencies to break the cycle.
Understanding lifecycle restrictions:
The replace_triggered_by argument only accepts managed resource references because Terraform needs to track planned changes to those resources. Variables and locals don't have "planned actions" in Terraform's execution model, so they can't trigger lifecycle actions directly.
Using terraform_data for flexibility:
The terraform_data resource is a meta-resource that allows you to create resource-like behavior for values that aren't infrastructure. This is the recommended pattern when you need variable-based replacement triggers.
Conditional creation with for_each/count:
When using replace_triggered_by with resources that use for_each or count, you can reference specific instances:
resource "aws_instance" "app" {
for_each = var.instances
lifecycle {
replace_triggered_by = [
aws_security_group.app[each.key] # Reference matching instance
]
}
}Version compatibility:
- Terraform 1.2+: Full replace_triggered_by support
- Terraform < 1.2: Use triggers in null_resource with local-exec provisioner as workaround
- Terrascan and other static analyzers may not recognize replace_triggered_by if they use outdated Terraform parsing
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