hashicorp/terraform · critical
State migration failed: %w
Error message
State migration failed: %w
What it means
The top-level failure returned by `terraform state migrate` when Meta.backendMigrateState(migrateOpts) returns an error. backendMigrateState is the orchestrator that copies state from the source backend to the destination backend; any failure in locking, reading source state, writing destination state, or backend-specific transfer surfaces here wrapped as %w. The preceding view.Log already printed StateMigrationFailureMessage naming source and destination.
Source
Thrown at internal/command/state_migrate.go:336
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Unknown migration destination",
"No configuration was provided for where to migrate the state to. Please ensure that a file with a .tf extension is present and contains valid state_store or backend configuration inside the terraform block.",
))
}
// present all errors from above together so user can fix them all at once
if diags.HasErrors() {
view.Diagnostics(diags)
return 1
}
view.Log(views.StateMigrationStartMessage, source, destination)
// Perform the migration from source to destination
err := c.Meta.backendMigrateState(migrateOpts)
if err != nil {
diags = diags.Append(fmt.Errorf("State migration failed: %w", err))
view.Diagnostics(diags)
view.Log(views.StateMigrationFailureMessage, source, destination)
return 1
}
// After a successful migration to a state store, we must make sure the dependency lock file contains the
// details of the destination state store provider.
if rootMod.StateStore != nil {
originalLocks, originalLockDiags := c.lockedDependencies()
diags = diags.Append(originalLockDiags)
if originalLockDiags.HasErrors() {
view.Diagnostics(diags)
return 1
}
// Get the combination of locks
//
// Take the lock from the destination provider download and add in the original locks from the dependency lock file.View on GitHub (pinned to c9def3e214)
Solutions
- Read the wrapped %w — it states the concrete failure (lock, auth, write).
- If the lock is stuck from a crashed process, force-unlock: `terraform force-unlock <LOCK_ID>`.
- Verify destination backend credentials and write permissions, then re-run `terraform state migrate`.
- Ensure no other Terraform process is operating on the same state, then retry.
Example fix
# before - migrating while a stale lock remains terraform state migrate # State migration failed: Failed to lock state: lock info... # after terraform force-unlock <LOCK_ID> terraform state migrate
Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: confirm source lock is free and destination is writable.
// (Backend-specific; example for local lock file)
func lockIsFree(path string) bool {
_, err := os.Stat(path + ".tflock")
return os.IsNotExist(err)
} Try / catch
// retry transient migration failures (lock contention / network) with backoff
for attempt := 0; attempt < 3; attempt++ {
if err := backendMigrateState(opts); err != nil {
if isTransient(err) {
time.Sleep(backoff(attempt))
continue
}
return err
}
break
} Prevention
- Ensure no other Terraform process runs against the same state during migration.
- Verify destination backend credentials/permissions before migrating.
- Force-unlock stale locks from crashed runs before retrying.
- Run migrations during a maintenance window to avoid lock contention.
When it happens
Trigger: Running `terraform state migrate` where the actual state transfer fails: source backend cannot acquire/release its state lock, destination backend write/lock fails, network/auth error to S3/cloud/HTTP backend, or incompatible backend implementations.
Common situations: Migrating to S3 without bucket write/IAM permissions; state lock held by another running operation; stale lock from a crashed run; HCP/TFE token expired or lacking workspace access; cross-region bucket misconfiguration; concurrent applies holding the lock.
Related errors
- Error inspecting states in the %q backend: %s Prior to
- Can't serialize backend configuration as JSON: %s
- Failed to refresh state: %s
- default workspace not supported You can create a new workspa
- workspaces not supported
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/9039c543bdf413c8.
Report an issue: GitHub.