TerraformPilot

DevOps

Fix Terraform Error - Provider Produced Inconsistent Result After Apply

Fix 'provider produced inconsistent result' errors in Terraform. Handle API normalization, default values, computed fields, and provider bugs.

LLuca Berton1 min read

Quick Answer

#

The cloud API returned a value different from what Terraform expected after applying. This is usually a provider bug (API normalizes values) or a computed attribute that changes server-side. Workaround with ignore_changes lifecycle or upgrade the provider.

The Error

#
Error: Provider produced inconsistent result after apply
 
When applying changes to aws_security_group.web, the provider
produced an unexpected new value for was present, but now absent.

What Causes This

#

1. API Normalization

#

The cloud API reformats your input. For example:

  • JSON policy gets reordered/whitespace-normalized
  • CIDR 10.0.0.0/16 becomes 10.0.0.0/16 (trailing zeros stripped)
  • Tags get lowercased or trimmed

2. Server-Side Defaults

#

The API adds fields you didn't specify, and the provider doesn't handle them correctly.

3. Provider Bug

#

The provider doesn't properly reconcile what it sent vs. what the API returned.

4. Eventual Consistency

#

AWS services like IAM may take time to propagate; Terraform reads back stale data.

How to Fix It

#

Solution 1: Upgrade the Provider

#
terraform init -upgrade
terraform plan
# Many inconsistency bugs are fixed in newer provider versions

Solution 2: Use ignore_changes

#
resource "aws_security_group" "web" {
  name   = "web-sg"
  vpc_id = aws_vpc.main.id
 
  lifecycle {
    ignore_changes = [
      ingress,  # Ignore if API reorders ingress rules
      tags,     # Ignore if API normalizes tags
    ]
  }
}

Solution 3: Normalize JSON Inputs

#
# ❌ Raw JSON string — API may reorder keys
resource "aws_iam_role" "main" {
  assume_role_policy = <<-EOF
    {"Version":"2012-10-17","Statement":[...]}
  EOF
}
 
# ✅ Use jsonencode — canonical key ordering
resource "aws_iam_role" "main" {
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = { Service = "ec2.amazonaws.com" }
    }]
  })
}

Solution 4: Apply Again

#

Sometimes the second apply succeeds because state now matches reality:

terraform apply  # May succeed on retry

Solution 5: Refresh State

#
terraform apply -refresh-only  # Sync state with actual cloud values
terraform plan                 # Check if issue is resolved

Common Resources with This Issue

#
ResourceCauseFix
aws_security_groupRule reorderingignore_changes = [ingress, egress]
aws_iam_rolePolicy JSON normalizationUse jsonencode()
aws_s3_bucketACL/CORS defaultsUpgrade provider
azurerm_*API returns extra fieldsUpgrade provider

Troubleshooting Checklist

#
  1. ✅ Is this a known provider bug? (Check GitHub issues)
  2. ✅ Are you on the latest provider version?
  3. ✅ Can you use jsonencode() for policy documents?
  4. ✅ Does ignore_changes work as a workaround?
  5. ✅ Does a second terraform apply succeed?
#

Conclusion

#

"Inconsistent result after apply" is usually a provider bug where the API normalizes values differently than expected. Upgrade the provider first, use jsonencode() for policies, and ignore_changes as a last resort. Report persistent issues on the provider's GitHub.

#Terraform#Troubleshooting#DevOps#Error Fix#Infrastructure as Code

Share this article