A postcondition validation check in your Terraform configuration evaluated to false, blocking the apply operation. This typically indicates a resource doesn't meet expected criteria after creation.
Terraform postconditions are validation checks that run after a resource is created or a data source is read. They use the `lifecycle` block with a condition expression and optional error message. When a postcondition evaluates to false, Terraform stops the operation and reports an error with your custom message. Postconditions were introduced in Terraform 1.2 to help catch configuration problems and permission issues earlier in the deployment pipeline.
The postcondition error includes your custom error_message which describes what went wrong. Read this message to understand what condition failed and what values were expected versus actual.
Example error output:
Error: Resource postcondition failed
on main.tf line 15, in resource "aws_instance" "example":
15: postcondition {
Postcondition failed: instance does not have a public IP address assignedThe error message "instance does not have a public IP address assigned" tells you exactly what the postcondition expected.
Examine the lifecycle block's condition attribute to understand what it's checking. Make sure:
- The condition references the correct resource attributes
- The attribute names match the actual resource schema
- The comparison logic is correct (e.g., != "" vs != null)
Example postcondition that fails:
resource "aws_instance" "example" {
# ... resource configuration ...
lifecycle {
postcondition {
condition = self.public_ip != ""
error_message = "instance does not have a public IP address assigned"
}
}
}If the instance doesn't get a public IP (e.g., no public subnet), this postcondition fails.
Check if the resource configuration actually satisfies the postcondition requirements. For example:
- Is the instance launched in a public subnet? (needed for public IP)
- Do you have the right IAM permissions? (needed for permission checks)
- Is the resource configuration correct? (missing required arguments?)
Run terraform plan to see what will be created:
terraform plan -out=tfplanExamine the planned resource attributes to see if they'll satisfy your postcondition.
Modify your resource configuration to ensure it will meet the postcondition requirements. Common fixes:
For network-related postconditions:
resource "aws_instance" "example" {
# ... other config ...
associate_public_ip_address = true # Ensures public IP is assigned
subnet_id = aws_subnet.public.id # Use public subnet
}For permission-related postconditions:
# Verify IAM role has required permissions
resource "aws_iam_role_policy" "example" {
name = "example-policy"
role = aws_iam_role.example.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "ec2:DescribeInstances"
Resource = "*"
}]
})
}After making changes, run terraform plan again to verify the postcondition will pass.
If the postcondition is checking for something optional or environment-specific, you can:
Remove the postcondition entirely if it's no longer needed:
resource "aws_instance" "example" {
# ... resource configuration ...
# Remove the lifecycle block
}Make the postcondition optional using can() or try():
lifecycle {
postcondition {
condition = try(self.public_ip != "", true) # Pass if public_ip doesn't exist
error_message = "instance should have a public IP"
}
}Adjust the condition to be less strict:
lifecycle {
postcondition {
condition = can(self.private_ip) # Just verify private IP exists
error_message = "instance must have a private IP"
}
}After fixing your configuration, run apply to verify the postcondition passes:
terraform apply tfplanIf the postcondition still fails:
1. Check the actual resource attributes that Terraform created (view in AWS console or with terraform state)
2. Compare them against your condition expression
3. Verify the condition logic is correct
4. Update the resource configuration or postcondition and try again
If it succeeds, the resource is created and your infrastructure is valid!
Understanding Condition Evaluation Timing:
Postconditions are evaluated as early as possible during the plan phase. However, if the condition depends on unknown values (like resource IDs or computed attributes), Terraform postpones evaluation until the apply phase. This means the condition may fail after the resource is partially created, which can leave your infrastructure in an unexpected state.
Known Limitations:
- Postconditions are NOT supported on output blocks (only preconditions)
- If a postcondition fails on a resource, dependent resources won't be created, preventing cascading changes
- In Terraform 1.2-1.4, there was a bug where postconditions would prevent terraform destroy from working. Upgrade to the latest version if you encounter this.
Using self in Postconditions:
The self keyword refers to the resource being validated and is only available in postcondition blocks. It gives you access to all computed attributes after the resource is created:
postcondition {
condition = self.id != ""
error_message = "Resource must have an ID"
}Permission Checks at Plan Time:
Postconditions can reference data sources like aws_iam_principal_policy_simulation to verify IAM permissions before apply. This helps catch permission issues during plan rather than at apply time:
postcondition {
condition = try(
data.aws_iam_principal_policy_simulation.test.result == "allowed",
false
)
error_message = "IAM role lacks required permissions"
}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