How to fix Error: State migration failed in Terraform

TerraformADVANCEDHIGHUpdated Dec 31, 2025· 109 views

State migration fails when Terraform cannot automatically transfer state from an old backend to a new one. This typically occurs due to version mismatches, lock conflicts, permissions issues, or backend connectivity problems during terraform init -migrate-state.

Quick fix

Fixes Error: State migration failed

# For S3 backend
aws s3 ls s3://your-bucket-name/ --region us-east-1

# For Azure blob storage
az storage blob list --container-name tfstate --account-name youraccount

# For Google Cloud Storage
gsutil ls gs://your-terraform-state-bucket/
  1. Verify backend connectivity and credentials
  2. Check for locks on both backends
  3. Use -reconfigure instead of -migrate-state
  4. Manually backup and migrate state
terraform — error
# For S3 backend
aws s3 ls s3://your-bucket-name/ --region us-east-1
# For Azure blob storage
az storage blob list --container-name tfstate --account-name youraccount
# For Google Cloud Storage
gsutil ls gs://your-terraform-state-bucket/
Error: State migration failed

What this error means

When you change your Terraform backend configuration and run terraform init -migrate-state, Terraform attempts to copy your existing state from the old backend to the new one. If this operation fails, it indicates a problem transferring the state file. This is a critical issue because it blocks you from initializing your infrastructure on the new backend and can result in state becoming out of sync between the old and new locations.

Typical symptoms

  • terraform init -migrate-state exits with 'State migration failed' error
  • State copy operation hangs or times out during backend migration
  • Error acquiring state lock on the target backend during migration
  • Insufficient permissions error when accessing target backend
  • terraform init fails to validate state during migration
  • Backend connection errors prevent state transfer from completing

Common causes

  1. Target backend is unreachable or experiencing connectivity issues
  2. Missing or incorrect credentials for the target backend
  3. Insufficient permissions in target backend to read/write state
  4. State lock held by another process on either source or target backend
  5. Source and target backends have incompatible state versions
  6. Network timeout during large state file transfer
  7. Target backend storage is full or has quota limits
  8. Terraform version mismatch between environments

How to fix "Error: State migration failed"

1Verify backend connectivity and credentials

Before attempting migration, ensure both backends are accessible. Test your target backend credentials:

bash
# For S3 backend
aws s3 ls s3://your-bucket-name/ --region us-east-1

# For Azure blob storage
az storage blob list --container-name tfstate --account-name youraccount

# For Google Cloud Storage
gsutil ls gs://your-terraform-state-bucket/

If any of these commands fail, fix the credential or connectivity issue before attempting migration again. Ensure your IAM user/service account has read, write, and delete permissions on the target backend.

2Check for locks on both backends

State locks prevent concurrent access during migrations. Force unlock both backends if necessary:

bash
# Check for locks
terraform state list

# Force unlock if a stale lock exists
terraform force-unlock <lock-id>

You can also manually remove lock files if available (e.g., .tflock files in Azure Blob Storage). Only force unlock if you're certain no one else is currently modifying the infrastructure.

3Use -reconfigure instead of -migrate-state

If migration continues to fail, switch to -reconfigure mode instead. This tells Terraform to reinitialize without copying state:

bash
terraform init -reconfigure

After this, you can manually migrate state using terraform state pull/push:

bash
terraform state pull > /tmp/backup.tfstate
terraform state push /tmp/backup.tfstate

This two-step approach gives you more control and lets you verify each step. Always keep a backup like we did above.

4Manually backup and migrate state

If automatic migration fails, perform a manual state migration. First, initialize with the old backend configuration:

bash
terraform init  # Uses old backend config
terraform state pull > /tmp/terraform.tfstate.backup

Then switch backend configuration and migrate manually:

bash
terraform init -reconfigure  # Switch to new backend
terraform state push /tmp/terraform.tfstate.backup

Verify the state transferred correctly:

bash
terraform state list
terraform state show

Keep the backup file indefinitely as a recovery point.

5Increase timeout and retry migration

Large state files can timeout during migration. Retry with increased wait time:

bash
terraform init -migrate-state -lock-timeout=15m

This tells Terraform to wait up to 15 minutes for locks to be released. If the state file is very large (over 100MB), split it by migrating resources in batches:

bash
terraform state rm 'module.large_module[0]'
terraform init -migrate-state
terraform state push previous-backup.tfstate
terraform import module.large_module[0].aws_instance.main i-12345
6Verify state integrity after migration

After successful migration, verify the state wasn't corrupted:

bash
terraform validate
terraform plan -out=tfplan

Review the plan output to ensure it accurately reflects your infrastructure. If the plan shows unexpected resource replacements or deletions, the migration may have introduced inconsistencies. In that case:

bash
terraform state show <resource>
terraform state list | wc -l  # Count resources
terraform refresh

If problems persist, restore from the backup and contact HashiCorp support with the error logs.

Advanced notes

State Lineage: Terraform tracks state lineage (version history) to prevent accidental overwrites. If migrating between drastically different backends, you may need to force override lineage checks by editing the backup tfstate JSON file's lineage field to match the target.

DynamoDB Lock Migration: If migrating from DynamoDB state locking to native S3 locking, run terraform init -reconfigure first to avoid migration conflicts.

Large State Files: State files over 100MB can experience timeout issues. Consider splitting your configuration into multiple modules or using separate workspaces to reduce state size.

Automation: In CI/CD, use -force-copy with -migrate-state to automate migration without prompts:

bash
terraform init -migrate-state -force-copy

Always run this in a protected CI/CD pipeline with state backup enabled.

Cross-Cloud Migration: Migrating between AWS S3, Azure Blob, and GCS requires careful credential management. Use separate terraform configs with -backend-config flags to avoid mixing credentials.

Frequently asked questions

What does "Error: State migration failed" mean?
When you change your Terraform backend configuration and run terraform init -migrate-state, Terraform attempts to copy your existing state from the old backend to the new one. If this operation fails, it indicates a problem transferring the state file. This is a critical issue because it blocks you from initializing your infrastructure on the new backend and can result in state becoming out of sync between the old and new locations.
How do I fix "Error: State migration failed"?
State migration fails when Terraform cannot automatically transfer state from an old backend to a new one. This typically occurs due to version mismatches, lock conflicts, permissions issues, or backend connectivity problems during terraform init -migrate-state.
What causes "Error: State migration failed"?
Target backend is unreachable or experiencing connectivity issues Missing or incorrect credentials for the target backend Insufficient permissions in target backend to read/write state
Is the "Error: State migration failed" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading