What's Actually Happening
Your Terraform commands fail with errors about provider plugin checksums, authentication failures, or corrupted cache files. The provider was working before, but now Terraform refuses to use it even after clean init attempts.
The Error You'll See
Checksum mismatch:
```bash $ terraform init
Error: Failed to install provider
Error while installing hashicorp/aws v5.0.0: the cached package for registry.terraform.io/hashicorp/aws 5.0.0 (in .terraform/providers) does not match any of the checksums provided by the registry ```
Plugin cache corrupt:
```bash $ terraform plan
Error: Failed to load plugin
Plugin reinitialization required. Please run "terraform init". Error: checksum for provider "aws" does not match expected value
Expected: h1:abc123... Got: h1:def456... ```
Authentication error in cache:
```bash $ terraform init
Error: Failed to query available provider packages
Could not retrieve the list of available versions for provider hashicorp/aws: the cached package metadata has been corrupted ```
Lock file mismatch:
```bash $ terraform init
Error: Provider locked to different version
The provider hashicorp/aws is locked to version 5.0.0 in .terraform.lock.hcl but the cached plugin appears to be for a different version or has been corrupted ```
Why This Happens
- 1.Partial download - Provider download interrupted mid-transfer
- 2.Network issues - Corrupted download from registry
- 3.Disk issues - Filesystem corruption in cache directory
- 4.Concurrent access - Multiple Terraform processes accessing cache
- 5.Manual tampering - Files modified in .terraform directory
- 6.Version mismatch - Lock file doesn't match cached plugin
- 7.Platform wrong - Cached plugin for wrong OS/architecture
- 8.Registry update - Provider re-released with different checksum
Step 1: Identify Cache Location and Contents
```bash # Check plugin cache location: terraform init -upgrade 2>&1 | grep -i cache
# Default cache locations: # Linux/macOS: ~/.terraform.d/plugin-cache # Windows: %APPDATA%\terraform.d\plugin-cache # Or in terraform.rc/terraform.tfrc: # plugin_cache_dir = "$HOME/.terraform.d/plugin-cache"
# Check .terraform directory: ls -la .terraform/providers/
# Output: # registry.terraform.io/ # └── hashicorp/ # ├── aws/ # │ └── 5.0.0/ # │ └── linux_amd64/ # │ └── terraform-provider-aws_v5.0.0_x5 # └── azurerm/ # └── 3.0.0/
# Check global plugin cache: ls -la ~/.terraform.d/plugin-cache/ 2>/dev/null || echo "No global cache"
# Check lock file: cat .terraform.lock.hcl
# Look for provider checksums: # provider "registry.terraform.io/hashicorp/aws" { # version = "5.0.0" # hashes = [ # "h1:abc123...", # ] # }
# Find all terraform data directories: find . -name ".terraform" -type d 2>/dev/null
# Check provider binary integrity: file .terraform/providers/registry.terraform.io/hashicorp/aws/5.0.0/linux_amd64/terraform-provider-aws_v5.0.0_x5 # Expected: ELF 64-bit LSB executable
# Check file size: du -h .terraform/providers/registry.terraform.io/hashicorp/aws/5.0.0/linux_amd64/* ```
Step 2: Clear Local .terraform Directory
```bash # Remove local terraform directory: rm -rf .terraform/
# Remove lock file (if needed): rm -f .terraform.lock.hcl
# Clear provider cache in user directory: rm -rf ~/.terraform.d/plugin-cache/
# On Windows: Remove-Item -Recurse -Force "$env:APPDATA\terraform.d\plugin-cache"
# Clear all terraform plugin caches: find ~ -name ".terraform" -type d -exec rm -rf {} + 2>/dev/null
# Clear provider plugin cache specifically: rm -rf ~/.terraform.d/plugins/
# Reinitialize terraform: terraform init -upgrade
# If still failing, force re-download: terraform init -upgrade -reconfigure
# For specific provider issues: terraform providers mirror /tmp/terraform-providers/ rm -rf .terraform/ terraform init -plugin-dir=/tmp/terraform-providers/ ```
Step 3: Fix Checksum Mismatch
```bash # Clear lock file and regenerate: rm -f .terraform.lock.hcl terraform init -upgrade
# If still fails, verify provider from registry:
# 1. Get expected checksum from registry: curl -s https://registry.terraform.io/v1/providers/hashicorp/aws/versions | \ jq '.versions[] | select(.version == "5.0.0") | .shasums'
# 2. Download SHASUM file: curl -sLo /tmp/shasums.txt \ https://releases.hashicorp.com/terraform-provider-aws/5.0.0/terraform-provider-aws_5.0.0_SHA256SUMS
# 3. Compare with cached file: sha256sum .terraform/providers/registry.terraform.io/hashicorp/aws/5.0.0/linux_amd64/terraform-provider-aws_v5.0.0_x5
# 4. Verify against registry: grep "$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m)" /tmp/shasums.txt
# If checksums don't match, provider is corrupted: rm -rf .terraform/providers/registry.terraform.io/hashicorp/aws/ terraform init -upgrade
# Force terraform to verify checksum: terraform init -upgrade -verify-plugins=true
# For air-gapped environments: # Download provider manually: curl -Lo terraform-provider-aws.zip \ https://releases.hashicorp.com/terraform-provider-aws/5.0.0/terraform-provider-aws_5.0.0_linux_amd64.zip
# Verify checksum: sha256sum terraform-provider-aws.zip
# Extract and place in correct location: unzip terraform-provider-aws.zip mkdir -p .terraform/providers/registry.terraform.io/hashicorp/aws/5.0.0/linux_amd64/ mv terraform-provider-aws_v5.0.0_x5 .terraform/providers/registry.terraform.io/hashicorp/aws/5.0.0/linux_amd64/ chmod +x .terraform/providers/registry.terraform.io/hashicorp/aws/5.0.0/linux_amd64/terraform-provider-aws_v5.0.0_x5 ```
Step 4: Configure Plugin Cache Correctly
```bash # Create terraform configuration file:
# Linux/macOS: ~/.terraformrc or ~/.terraform.tfrc # Windows: %APPDATA%\terraform.rc
cat << 'EOF' > ~/.terraformrc plugin_cache_dir = "$HOME/.terraform.d/plugin-cache" disable_checkpoint = true
provider_installation { filesystem_mirror { path = "$HOME/.terraform.d/plugin-cache" include = ["*/*/*"] } direct { exclude = ["*/*/*"] } } EOF
# Create cache directory: mkdir -p ~/.terraform.d/plugin-cache
# Set correct permissions: chmod 755 ~/.terraform.d/plugin-cache
# Verify configuration: terraform version -json | jq '.provider_selections'
# For CI/CD environments, use environment variable: export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache" export TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE=true
# For shared cache: cat << 'EOF' > ~/.terraformrc plugin_cache_dir = "/shared/cache/terraform-plugins" EOF
# Initialize with custom plugin directory: terraform init -plugin-dir=/shared/cache/terraform-plugins
# For filesystem mirror: terraform providers mirror /shared/cache/terraform-plugins/ ```
Step 5: Handle Provider Authentication Issues
```bash # Check if provider requires authentication: terraform init -upgrade
# For private registry (Terraform Cloud/Enterprise): # Login to Terraform Cloud: terraform login
# Or set token directly: export TF_TOKEN_app_terraform_io="your-token-here"
# For private provider registry: cat << 'EOF' > ~/.terraformrc credentials "app.terraform.io" { token = "your-token-here" } EOF
# Or use environment variable: export TF_REGISTRY_TOKEN="your-token-here"
# For GitHub-based private providers: # Set GitHub token: export GITHUB_TOKEN="ghp_xxxxx"
# Or in terraform.rc: cat << 'EOF' > ~/.terraformrc credentials "github.com" { token = "ghp_xxxxx" } EOF
# For GitLab private modules: export GITLAB_TOKEN="glpat-xxxxx"
# Clear cached credentials: rm -f ~/.terraform.d/credentials.tfrc.json
# Re-login: terraform login
# Verify credentials: cat ~/.terraform.d/credentials.tfrc.json
# For S3 backend with private providers: # Configure AWS credentials: aws configure
# Or set environment: export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE" export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" ```
Step 6: Fix Platform-Specific Provider Issues
```bash # Check current platform: uname -s # Linux, Darwin, Windows uname -m # x86_64, aarch64, arm64
# Check required platforms in lock file: cat .terraform.lock.hcl | grep -A 5 "provider \"" | grep -E "h1:|zh:"
# For cross-platform development:
# 1. Add required_providers with all platforms: terraform { required_providers { aws = { source = "hashicorp/aws" version = "5.0.0" } } }
# 2. Generate lock file for multiple platforms: terraform providers lock \ -platform=linux_amd64 \ -platform=linux_arm64 \ -platform=darwin_amd64 \ -platform=darwin_arm64 \ -platform=windows_amd64
# 3. Reinitialize: terraform init -upgrade
# If provider not available for your platform: # Check provider releases: curl -s https://releases.hashicorp.com/terraform-provider-aws/ | grep -o 'href="[^"]*"' | grep "$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m)"
# For Apple Silicon (M1/M2) issues: # Ensure Rosetta is installed: softwareupdate --install-rosetta
# Or use ARM64 binary: terraform providers lock -platform=darwin_arm64
# Verify provider platform: file .terraform/providers/registry.terraform.io/hashicorp/aws/*/darwin_arm64/terraform-provider-aws* # Expected: Mach-O 64-bit executable arm64 ```
Step 7: Debug Provider Loading
```bash # Enable debug logging: export TF_LOG=DEBUG export TF_LOG_PATH=terraform-debug.log
# Run terraform with debug: terraform init -upgrade
# Check debug log: grep -i "provider" terraform-debug.log | head -50 grep -i "checksum" terraform-debug.log grep -i "cache" terraform-debug.log
# Check provider resolution: terraform providers
# Output: # Providers required by configuration: # . # └── provider[registry.terraform.io/hashicorp/aws] ~> 5.0
# Trace provider download: export TF_LOG=TRACE terraform init -upgrade 2>&1 | tee init-trace.log
# Check which registry is being used: grep "registry.terraform.io" init-trace.log
# Check provider plugin path: terraform init -upgrade 2>&1 | grep "plugin directory"
# Verify provider binary works: .terraform/providers/registry.terraform.io/hashicorp/aws/5.0.0/linux_amd64/terraform-provider-aws_v5.0.0_x5 # Should print provider information
# Check for zombie processes: ps aux | grep terraform kill -9 $(pgrep -f terraform) # If stuck
# Check file locks: lsof | grep .terraform
# For stuck downloads: # Check network connectivity: curl -I https://releases.hashicorp.com/ curl -I https://registry.terraform.io/ ```
Step 8: Use Provider Mirroring for Air-Gapped Environments
```bash # Mirror all providers to local filesystem: terraform providers mirror /path/to/mirror/
# Output: # - registry.terraform.io/hashicorp/aws -> /path/to/mirror/registry.terraform.io/hashicorp/aws
# Configure terraform to use mirror: cat << 'EOF' > ~/.terraformrc provider_installation { filesystem_mirror { path = "/path/to/mirror" } } EOF
# Or use plugin-dir for specific mirror: terraform init -plugin-dir=/path/to/mirror
# For S3-based mirror: # 1. Download providers to S3: aws s3 sync /path/to/mirror/ s3://my-bucket/terraform-mirror/
# 2. Configure in terraform.rc: provider_installation { filesystem_mirror { path = "/tmp/terraform-cache" } }
# 3. Download from S3 before init: aws s3 sync s3://my-bucket/terraform-mirror/ /tmp/terraform-cache/ terraform init -plugin-dir=/tmp/terraform-cache
# For Terraform Enterprise/Cloud: # Use provider mocking or local execution mode
# Verify mirror works: terraform init -plugin-dir=/path/to/mirror -upgrade ```
Step 9: Fix State Lock Issues After Cache Clear
```bash # After clearing cache, check state: terraform state list
# If state lock stuck: terraform force-unlock <LOCK_ID>
# For S3 backend: aws dynamodb delete-item \ --table-name terraform-locks \ --key '{"LockID":{"S":"mybucket/mykey.tfstate"}}'
# For local backend: rm -f terraform.tfstate.lock.info
# Refresh state after cache clear: terraform refresh
# If state corrupted: # 1. Backup state: cp terraform.tfstate terraform.tfstate.backup
# 2. Pull remote state: terraform state pull > terraform.tfstate.new
# 3. Compare: diff terraform.tfstate terraform.tfstate.new
# 4. If needed, push corrected state: terraform state push terraform.tfstate.new
# For partial state issues: terraform state rm 'module.broken' terraform import 'module.broken.resource_name' 'resource_id' ```
Step 10: Implement Provider Cache Management
```bash # Create provider cache management script: cat << 'EOF' > /usr/local/bin/tf-cache-manager.sh #!/bin/bash
CACHE_DIR="${TF_PLUGIN_CACHE_DIR:-$HOME/.terraform.d/plugin-cache}" MAX_AGE_DAYS=30 MAX_SIZE_GB=10
echo "=== Terraform Provider Cache Manager ===" echo "Cache directory: $CACHE_DIR"
# Create cache dir if not exists mkdir -p "$CACHE_DIR"
# Show current cache size CACHE_SIZE=$(du -sh "$CACHE_DIR" 2>/dev/null | cut -f1) echo "Current cache size: $CACHE_SIZE"
# Find providers older than MAX_AGE_DAYS echo -e "\nProviders older than $MAX_AGE_DAYS days:" find "$CACHE_DIR" -name "terraform-provider-*" -mtime +$MAX_AGE_DAYS -exec ls -lh {} \;
# Clean old providers read -p "Clean providers older than $MAX_AGE_DAYS days? (y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then find "$CACHE_DIR" -name "terraform-provider-*" -mtime +$MAX_AGE_DAYS -delete echo "Old providers cleaned." fi
# Check for corrupted providers echo -e "\nChecking for corrupted providers..." find "$CACHE_DIR" -name "terraform-provider-*" -type f | while read -r provider; do if ! file "$provider" | grep -q "executable|archive"; then echo "Potentially corrupted: $provider" read -p "Remove? (y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then rm -f "$provider" fi fi done
# Show cache stats echo -e "\nCache Statistics:" echo "Total files: $(find "$CACHE_DIR" -type f | wc -l)" echo "Total size: $(du -sh "$CACHE_DIR" | cut -f1)" echo "Providers: $(find "$CACHE_DIR" -name "terraform-provider-*" | wc -l)"
# Check if over size limit SIZE_BYTES=$(du -sb "$CACHE_DIR" | cut -f1) MAX_SIZE_BYTES=$((MAX_SIZE_GB * 1024 * 1024 * 1024)) if [ "$SIZE_BYTES" -gt "$MAX_SIZE_BYTES" ]; then echo -e "\nWarning: Cache exceeds $MAX_SIZE_GB GB" echo "Consider running: terraform providers mirror" fi
echo -e "\nCache management complete." EOF
chmod +x /usr/local/bin/tf-cache-manager.sh
# Add to crontab for weekly cleanup: # 0 0 * * 0 /usr/local/bin/tf-cache-manager.sh >> /var/log/tf-cache.log 2>&1
# Best practices: # 1. Use consistent plugin_cache_dir across team # 2. Exclude .terraform from version control # 3. Commit .terraform.lock.hcl to version control # 4. Use terraform providers lock for air-gapped environments # 5. Monitor cache size in CI/CD # 6. Run terraform init -upgrade periodically ```
Terraform Provider Cache Checklist
| Check | Command | Expected |
|---|---|---|
| Cache exists | ls ~/.terraform.d/plugin-cache | Directory present |
| Config valid | terraform version | No errors |
| Lock file | cat .terraform.lock.hcl | Checksums match |
| Provider binary | file provider-* | Executable |
| Checksums match | terraform init | No errors |
| Cache size | du -sh cache | Reasonable |
Verify the Fix
```bash # After fixing cache corruption:
# 1. Clear all caches rm -rf .terraform/ ~/.terraform.d/plugin-cache/ rm -f .terraform.lock.hcl
# 2. Reinitialize terraform init -upgrade # Output: Terraform has been successfully initialized!
# 3. Verify providers terraform providers # Output: All providers listed correctly
# 4. Run plan terraform plan # Output: No errors, plan created successfully
# 5. Check lock file cat .terraform.lock.hcl # Output: All provider checksums present
# 6. Verify cache is populated ls -la ~/.terraform.d/plugin-cache/ 2>/dev/null || echo "Using .terraform directory"
# 7. Test on different machine # After git clone, run terraform init # Should use lock file checksums correctly
# Compare before/after: # Before: Checksum mismatch, provider errors # After: Clean init, providers work correctly ```
Related Issues
- [Fix Terraform State Lock Error](/articles/fix-terraform-state-lock-error)
- [Fix Terraform Provider Not Found](/articles/fix-terraform-provider-not-found)
- [Fix Terraform Init Failed](/articles/fix-terraform-init-failed)