hashicorp/terraform · error
Error copying state from the previous %q backend to the newl
Error message
Error copying state from the previous %q backend to the newly configured
%q backend:
%s
The state in the previous backend remains intact and unmodified. Please resolve
the error above and try again. What it means
Returned by backendMigrateState_s_s when statemgr.Migrate(destinationState, sourceState) at line 456 fails — the confirmed copy/merge of source state into the destination state manager errored. The message errBackendStateCopy stresses the SOURCE remains intact (migration is a copy), so re-running is safe once the destination issue is fixed.
Source
Thrown at internal/command/meta_backend_migrate.go:457
// 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, opts.DestinationType, 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, opts.DestinationType, err)
}
// And we're done.
return nil
}
func (m *Meta) backendMigrateEmptyConfirm(source, destination statemgr.Full, opts *backendMigrateOpts) (bool, error) {
var inputOpts *terraform.InputOpts
if opts.DestinationType == "cloud" {View on GitHub (pinned to c9def3e214)
Solutions
- Read the inner %s for the Migrate-level failure (write error, lineage conflict, size limit).
- Fix destination write permissions / capacity, then re-run 'terraform init' — source is unchanged.
- If lineage conflicts, decide which state is authoritative and manually 'terraform state push' it after clearing the destination.
- For size limits (e.g., remote backend), reduce state size or use a backend with higher limits.
- Check destination backend logs for the rejected write payload.
Example fix
// before: destination write denied mid-Migrate // Error copying state: ... AccessDenied on PutObject // after: grant write and retry (source intact) // (attach s3:PutObject policy) // terraform init
Defensive patterns
Strategy: validation
Validate before calling
# Verify destination write access + lineage compatibility before migrating.
aws s3api put-object --bucket "$TF_DST_BUCKET" --key "$TF_DST_KEY.migrationprobe" --body /dev/null >/dev/null \
|| { echo 'destination not writable'; exit 1; }
aws s3 rm "s3://$TF_DST_BUCKET/$TF_DST_KEY.migrationprobe"
# Compare lineage if both states present:
terraform state pull -state=/tmp/src.tfstate
# inspect .lineage vs destination's lineage to anticipate conflicts Try / catch
# Detect Migrate-level copy failure; source is intact so a retry is safe after fixing dst.
terraform init 2>/tmp/init.err || rc=$?
if grep -q 'Error copying state' /tmp/init.err; then
echo 'State copy failed — source intact. Fix destination write/lineage and retry.' >&2
fi
exit ${rc:-0} Prevention
- Grant write on the destination state path before migrating.
- Pre-check lineage conflicts (both non-empty with different lineage) and decide authoritative state.
- Ensure destination can accept the state size (remote backend limits).
- Back up destination state before overwrite-style migrations.
When it happens
Trigger: After confirmation and locking, the actual state-copy operation (which preserves lineage/serial) fails: destination write failure, lineage conflict that Migrate can't reconcile, state schema incompatibility between source and destination managers. Wrapped at line 457-458.
Common situations: Destination backend write permission missing; destination state has a conflicting lineage with the source (both non-empty with different lineage — though the non-empty confirm prompt usually precedes this); large state exceeding destination size limits; remote backend rejecting the state version payload.
Related errors
- Error migrating the workspace %q from the previous %q backen
- Error loading state: %[2]s Terraform failed to load the
- Failed to set new workspace: %s
- Error saving temporary state: %s
- Can't ask approval for state migration when interactive inpu
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/b5f1c405837476ab.
Report an issue: GitHub.