October 28, 2021·4 min read·engineeringterraformstatebackends

Terraform repairs version checking during backend migration

Terraform 1.0.10 fixes destination-version checking for named remote workspaces. Its initialization fixes also restore migration locking options and prevent a disabled prompt from hanging automation.

Moving Terraform state into a hosted workspace involves two versions of Terraform. The local executable writes the migrated state, while the destination workspace may run another executable. A migration must account for that relationship before uploading state. Terraform 1.0.10, released on October 28, corrects how the remote backend performs that check.

The underlying mistake concerns workspace naming. A remote backend configured for one explicitly named workspace did not populate the destination-workspace list used by the migration check. The loop that applied the intended compatibility check therefore did not run for that case. The code fell back to a string-equality check, according to the patch description.

I think these administrative paths deserve close attention because Terraform's configuration abstraction depends on retaining usable state. Reusable resource declarations do not make state transport interchangeable with copying an arbitrary document. The destination's execution requirements still matter when a different local executable performs the copy.

A named destination still needs checking

Alisdair McDiarmid's pull request 29793 identifies two bugs. One is the empty destination list for the backend's name strategy. The other is that the CLI's -ignore-remote-version setting did not apply to the migration version check.

The first correction adds a fallback when the destination-workspace list is empty. It calls the remote backend version check using Terraform's default state name. That carries the single-workspace case through the same intended compatibility mechanism instead of allowing the absence of iteration to determine the behavior.

The difference between a workspace's naming strategy and its existence is important. This patch discusses migration to an existing Terraform Cloud workspace. Its problem is that the chosen naming mode leaves a collection empty, not that a destination object needs creation. An empty internal list does not establish that the destination has no version requirement.

The second correction applies an explicitly requested remote-version override to the destination backend. Otherwise, the normal compatibility check runs across the destination workspaces or the single-workspace fallback. This describes the flag's repaired behavior, rather than making it a requirement for migration. The default path continues to check compatibility.

The patch also documents why the source receives different treatment. Migration is moving away from that backend, so the operation disregards the source remote version conflict. The destination is where uploading a state snapshot could affect subsequent runs. Source and destination have different responsibilities in this check.

Initialization can perform a state operation

Another fix in the same release restores -lock and -lock-timeout to terraform init. They were removed in 0.15.0 because they were thought to have no effect. Pull request 29773 explains that they do matter during backend state migration.

This is a useful correction to an overly narrow interpretation of initialization. The command installs dependencies, but it can also migrate state when backend settings change. A command that can copy state needs the coordination behavior associated with that operation, even if most invocations only prepare a working directory.

The restored help text describes -lock-timeout as a duration for retrying a state lock. With backend settings already changed and migration intended, the restored option can be expressed directly:

terraform init -migrate-state -lock-timeout=30s

The example sets a waiting period. It does not disable locking. The patch restores locking as enabled by default, and its test creates a locked source state before attempting migration. The expected failure demonstrates that migration actually uses the locking behavior that the removed options were assumed not to affect.

That test also exercises the explicit lock-disabling option, but it is evidence of the option's implementation rather than a recommended migration procedure. The help text warns about concurrent operations against the same workspace. The useful default is that migration participates in state coordination.

A noninteractive workspace error now terminates

The release's initialization changes also address a hang when selecting a workspace. Pull request 29805 describes a backend with multiple workspaces where the currently selected local workspace does not exist. Interactive initialization can ask the user to choose among available workspaces.

With -input=false, that prompt should not occur. Previously the command could wait for input anyway. The patch adds an explicit check before asking the question and returns an error naming the nonexistent selected workspace. Its regression test expects immediate failure in that case.

An automated caller can react to a reported configuration error. It cannot resolve an unexpected interactive question in a process that was explicitly told not to ask one. This correction preserves the meaning of noninteractive execution without inventing a destination choice on the caller's behalf.

I find the release coherent around these initialization details. The migration check now covers an explicitly named destination, state-lock options again apply to migration, and workspace selection respects disabled input. Each correction preserves information or intent that the administrative path already had but failed to carry into the operation that needed it.