hashicorp/terraform · error

Error copying state from the previous %[1]q %[2]s to the new

Error message

Error copying state from the previous %[1]q %[2]s to the newly configured
%[3]q %[4]s:
    %[5]s

The state in the previous %[2]s remains intact and unmodified. Please resolve
the error above and try again.

What it means

Returned by the single-to-single migration when `statemgr.Migrate(destinationState, sourceState)` fails after user confirmation and lock acquisition. The source state is preserved intact; the user is told to resolve the error and retry. Migrate preserves lineage/serial where possible.

Source

Thrown at internal/command/meta_backend_migrate.go:470

		// Confirm with the user whether we want to copy state over
		confirm, err := confirmFunc(sourceState, destinationState, opts)
		if err != nil {
			log.Print("[TRACE] backendMigrateState: error reading input, so aborting migration")
			return err
		}
		if !confirm {
			log.Print("[TRACE] backendMigrateState: user cancelled at confirmation prompt, so aborting migration")
			return nil
		}
	}

	// Confirmed! We'll have the statemgr package handle the migration, which
	// includes preserving any lineage/serial information where possible, if
	// both managers support such metadata.
	log.Print("[TRACE] backendMigrateState: migration confirmed, so migrating")
	if err := statemgr.Migrate(destinationState, sourceState); err != nil {
		return fmt.Errorf(strings.TrimSpace(errBackendStateCopy),
			opts.SourceType, srcWord,
			opts.DestinationType, dstWord, err)
	}
	// The backend is currently handled before providers are installed during init,
	// so requiring schemas here could lead to a catch-22 where it requires some manual
	// intervention to proceed far enough for provider installation. To avoid this,
	// when migrating to HCP Terraform backend, the initial JSON varient of state won't be generated and stored.
	if err := destinationState.PersistState(nil); err != nil {
		return fmt.Errorf(strings.TrimSpace(errBackendStateCopy),
			opts.SourceType, srcWord,
			opts.DestinationType, dstWord, err)
	}

	// And we're done.
	return nil
}

func (m *Meta) backendMigrateEmptyConfirm(source, destination statemgr.Full, opts *backendMigrateOpts) (bool, error) {

View on GitHub (pinned to d32a084675)

Solutions

  1. Align source and destination Terraform/OpenTofu versions before migrating.
  2. Inspect the embedded `%[5]s` error for the statemgr-specific failure (schema, lineage, size).
  3. If lineage conflicts, manually reconcile or pick one authoritative state and force.
  4. Retry `terraform init -migrate-state=true` after resolving the schema/lineage issue.
Defensive patterns

Strategy: validation

Validate before calling

# Align Terraform/OpenTofu versions between source and destination first.
# Example: pin the binary used for migration to match the source state version.
terraform version  # confirm matches the version that wrote the source state
terraform init -input=false -migrate-state=true

Try / catch

# Schema/lineage copy failures are not transient — report and stop:
if ! terraform init -input=false -migrate-state=true >/tmp/init.log 2>&1; then
  grep -q 'Error copying state' /tmp/init.log \
    && { echo 'State copy failed; check schema/lineage compatibility' >&2; exit 2; }
  cat /tmp/init.log; exit 1
fi

Prevention

When it happens

Trigger: Fires in `backendMigrateState_s_s` after confirmation when the actual state-copy primitive errors — schema/version incompatibility between source and destination state, out-of-memory on a very large state, or an internal statemgr assertion.

Common situations: Migrating across Terraform major versions whose state schemas differ, an extremely large state file, lineage/serial conflicts between two non-empty states, or a state file written by an incompatible fork.

Related errors


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