hashicorp/terraform · error

State migration failed

Error message

State migration failed: %w

What it means

Top-level wrapper around c.Meta.backendMigrateState(migrateOpts) during state migration. All the prior validation (config serialization, provider install, version checks) passed; the actual copy/move of state objects from source to destination backend failed. The wrapped err carries the migration-specific reason (lock, write, auth).

Solutions

  1. Read the wrapped err — it names the exact failed operation (PUT, lock, copy).
  2. Confirm destination backend IAM/permissions for write + lock (e.g. s3:PutObject, dynamodb:PutItem).
  3. If destination already has state, decide explicitly: clear it or pick a different destination key.
  4. Re-run after fixing; the migration is designed to be retried safely from source.

Example fix

# before
 terraform state migrate  # fails: AccessDenied on PutObject

# after (grant write on destination)
 aws iam attach-role-policy ... --policy-name S3Write
 terraform state migrate
Defensive patterns

Strategy: retry

Validate before calling

// Confirm destination writability before invoking migrate.
if w, ok := dstBackend.(interface{ WriteState(*states.State) error }); ok {
    if err := w.WriteState(nil); err != nil { return err }
}

Try / catch

err := c.Meta.backendMigrateState(migrateOpts)
if err != nil {
    diags = diags.Append(fmt.Errorf("State migration failed: %w", err))
    view.Diagnostics(diags)
    view.LogStateMigrationErrored(views.DuringMigration, source, destination)
    // Migration is idempotent from source — safe to retry once.
    return 1
}

Prevention

When it happens

Trigger: Source backend readable and destination writable, but the transfer fails: destination write returns 4xx/5xx, lock acquisition on destination times out, source changes mid-migration, network drops during a large state upload.

Common situations: Migrating state from local to S3 with wrong KMS key on destination bucket; destination bucket has versioning/acl that rejects the PUT; cross-account migration without object-write IAM; partial upload when the run is interrupted; destination workspace already has state.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/9039c543bdf413c8. Report an issue: GitHub.

Appendix: source

Thrown at internal/command/state_migrate.go:340

			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.LogMigrationDestinationInitializationComplete()

	view.LogStateMigrationStart(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.LogStateMigrationErrored(views.DuringMigration, source, destination)
		return 1
	}

	view.LogStateMigrationComplete()

	// 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)
			view.LogStateMigrationErrored(views.DuringLockfile, source, destination)
			return 1
		}

View on GitHub (pinned to d32a084675)