Terraform Error Guide: 'Provider produced inconsistent result after apply' (apply-time provider bug)
Fix Terraform's 'Provider produced inconsistent result after apply' error: upgrade the provider, use ignore_changes for eventual-consistency drift, retry, and report upstream.
- #terraform
- #troubleshooting
- #errors
- #providers
Exact Error Message
Provider produced inconsistent result after apply is an apply-time error. After Terraform sends a create or update to the provider, the value the provider reports back does not match what it promised during planning. Terraform treats the mismatch as a contract violation and fails the apply.
Error: Provider produced inconsistent result after apply
When applying changes to aws_lb.app, provider "registry.terraform.io/hashicorp/aws"
produced an unexpected new value: .subnet_mapping: block count changed from 0 to 2.
This is a bug in the provider, which should be reported in the provider's own
issue tracker.
Error: Provider produced inconsistent result after apply
When applying changes to google_compute_instance.vm, provider
"registry.terraform.io/hashicorp/google" produced an unexpected new value:
.metadata_fingerprint: was cty.StringVal(""), but now cty.StringVal("a1b2c3").
This is a bug in the provider...
Note the message itself says “This is a bug in the provider.” This is almost never something wrong with your configuration.
What the Error Means
During plan, the provider commits to the final shape of a resource. During apply, after the real API call, Terraform compares the actual returned attributes against that committed plan. If a value the provider said would be X comes back as Y — a block count changes, a fingerprint appears, a computed field is populated by the cloud — Terraform raises Provider produced inconsistent result after apply.
This is distinct from the plan-time error “Provider produced inconsistent final plan”, which fires during planning when the second pass disagrees with the first. The apply-time variant means the resource may have actually been created or modified in the cloud, but Terraform refuses to record a state it cannot trust. Re-running often succeeds because the cloud has now settled.
Common Causes
- Provider bugs. The provider’s schema or read logic does not round-trip an attribute correctly. This is the most common cause and is upstream, not yours.
- Eventual consistency / async cloud APIs. The create call returns before the resource fully settles, so an attribute that was empty at plan becomes populated by the time Terraform reads it back.
- Attributes set by the cloud after creation. Fingerprints, ARNs, default security group rules, auto-assigned IPs, or tags injected by the platform appear only post-create.
- Drift between plan and actual. A concurrent change (another pipeline, a console edit, an auto-scaling event) alters the resource between plan and apply.
- Known provider issues. Specific resources have documented inconsistency bugs tied to certain provider versions; an upgrade or pin resolves them.
How to Reproduce the Error
This error is non-deterministic by nature — it surfaces against real async APIs. A common trigger is a resource whose computed attributes the cloud backfills:
resource "aws_lb" "app" {
name = "app-lb"
load_balancer_type = "application"
subnets = var.subnet_ids
# The platform may add subnet_mapping blocks the provider did not model,
# so the post-apply read disagrees with the plan.
}
resource "google_compute_instance" "vm" {
name = "settle-test"
machine_type = "e2-small"
zone = "us-central1-a"
# metadata_fingerprint is assigned by GCP after creation.
}
terraform apply -auto-approve
Error: Provider produced inconsistent result after apply
When applying changes to aws_lb.app, provider produced an unexpected new
value: .subnet_mapping: block count changed from 0 to 2.
Diagnostic Commands
Confirm the failing resource and attribute:
terraform apply 2>&1 | grep -A3 "inconsistent result after apply"
Check the exact provider versions in play — version is the single biggest factor:
terraform version
terraform providers
cat .terraform.lock.hcl | grep -A2 'provider "registry'
Re-run with debug logs to capture the API round-trip for an upstream report:
TF_LOG=DEBUG terraform apply 2>&1 | tee apply-debug.log
Inspect what actually landed in state and the cloud after the failure:
terraform state show aws_lb.app
terraform refresh # reconcile state with the now-settled resource
Step-by-Step Resolution
1. Re-apply once. Because the resource often exists and the cloud has now settled, a second apply frequently succeeds with no changes:
terraform apply
2. Upgrade the provider. Most inconsistency bugs are fixed in newer releases. Bump the constraint and update the lock:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.40.0"
}
}
}
terraform init -upgrade
3. Suppress cloud-backfilled attributes with lifecycle. If the cloud sets an attribute you do not manage, tell Terraform to ignore it:
resource "aws_lb" "app" {
# ...
lifecycle {
ignore_changes = [subnet_mapping]
}
}
4. Handle eventual consistency with refresh and retries. A terraform refresh (or re-plan) after the resource settles reconciles state; in CI, wrap the apply in a bounded retry:
for i in 1 2 3; do terraform apply -auto-approve && break; sleep 15; done
5. Pin to a known-good version if an upgrade regresses. If the latest provider reintroduces the issue, pin to the last working release in .terraform.lock.hcl and terraform init.
6. Report it upstream. Since the message explicitly says it is a provider bug, file an issue on the provider’s tracker with the resource, attribute, provider version, and the TF_LOG=DEBUG excerpt. This is the path to a permanent fix.
Prevention and Best Practices
- Keep providers reasonably current and pin exact versions in
.terraform.lock.hclso applies are reproducible and upgrades are deliberate. - Use
ignore_changesfor attributes the cloud platform owns (fingerprints, auto-assigned IPs, injected tags) rather than fighting the provider. - Serialize Terraform runs against shared infrastructure (state locking, single pipeline) to avoid concurrent drift between plan and apply.
- Build bounded retries into CI for resources backed by eventually-consistent APIs (load balancers, IAM propagation, DNS).
- Treat this as a provider bug, not a config error — search the provider’s issue tracker before rewriting your HCL.
- For triage, the free incident assistant can map the failing attribute to a known provider issue and version. More patterns in the Terraform guides.
Related Errors
- Provider produced inconsistent final plan — the plan-time sibling of this error; the second planning pass disagrees with the first. See that guide for plan-stage mismatches; this guide covers the post-
applyvariant. - Invalid for_each argument — a plan-time error where computed values prevent expansion, also rooted in provider-computed attributes.
- Error: Provider configuration not present — a provider was removed from config while resources still reference it; a different provider lifecycle failure.
- Resource depends on a value not yet known — upstream computed values that can also trigger post-apply surprises.
Frequently Asked Questions
Is Provider produced inconsistent result after apply my fault?
Almost never. The error message itself states it is a bug in the provider. Your configuration triggered an attribute the provider does not round-trip correctly, but the defect is in the provider’s schema or read logic, not your HCL.
Did the resource actually get created when this error appeared?
Often yes. The error happens after the API call, so the cloud resource may exist even though Terraform refused to record the state. Run terraform refresh or terraform plan to see the real state, and re-apply to reconcile.
Why does re-running terraform apply make it go away?
Many cases are eventual consistency: an attribute that was empty at plan time is populated by the cloud moments later. On the second run the value is already settled, so the plan and the post-apply read agree.
How is this different from “inconsistent final plan”? “Inconsistent final plan” is a plan-time error — Terraform’s second planning pass disagrees with the first, before any change is applied. “Inconsistent result after apply” happens after the real API call, comparing the promised plan to the actual returned value. Different stage, different guide.
Should I use ignore_changes or upgrade the provider?
Prefer upgrading the provider — it fixes the root cause. Use ignore_changes when the attribute is genuinely cloud-owned (a fingerprint or injected default) and you do not want Terraform to manage it, or as a stopgap while you wait for an upstream fix.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.