Terraform state migration must allow a workspace to be created
Terraform 0.14.9 fixes a version check that rejected a new remote workspace before migration could create it. The distinction between an absent workspace and a failed lookup is the core of the change.
A compatibility check can be correct for an existing object and wrong during its creation. Terraform's remote backend encountered that distinction when moving existing state into a new hosted workspace. The version check tried to fetch the destination workspace, received a not-found response, and stopped the migration. Terraform 0.14.9, released on March 24, fixes that sequence.
The release contains a single listed bug fix, but the problem is broader than an inconvenient error message. A migration needs to preserve existing state while establishing a destination that may not yet exist. The preparation path cannot assume every destination object is already present. In this case, a check meant to protect state compatibility prevented the backend from reaching its documented workspace-creation behavior.
I regard state handling as one of the places where Terraform's usefulness depends on precise implementation details. The configuration language makes infrastructure reusable, but moving its record of that infrastructure is an administrative operation with its own ordering requirements. A failed precondition needs to mean what the code thinks it means.
Why the missing workspace was legitimate
The remote backend documentation at this release explicitly permits an absent destination. When existing state is present during terraform init, Terraform can create corresponding remote workspaces if they are absent, or update their state if they are empty. Creating the workspace is part of the supported migration path.
A single-workspace configuration names its destination in a nested block:
terraform {
backend "remote" {
organization = "example-company"
workspaces {
name = "network-production"
}
}
}
The names in this example are placeholders. The backend defaults its hostname to app.terraform.io, and the documentation recommends supplying authentication through terraform login or CLI credentials instead of embedding a token in configuration. Nothing about the new fix changes those requirements.
The backend can alternatively map several CLI workspaces through a common prefix. That is a different naming mode, and the documentation requires exactly one of name or prefix. A missing destination still has a legitimate meaning when initialization is responsible for establishing the corresponding hosted workspace. It cannot automatically be classified as an incompatible workspace.
This gives the version check an important logical boundary. An existing workspace may have a Terraform version that needs comparison. A workspace that has not yet been created has no existing version setting for that comparison to reject. Failing to retrieve that nonexistent setting supplies no evidence of version incompatibility.
The patch distinguishes absence from failure
Alisdair McDiarmid's pull request 28093 documents the failure directly. VerifyWorkspaceTerraformVersion called the workspace lookup and treated its error as a diagnostic. The correction adds a specific branch for tfe.ErrResourceNotFound, returning without a version diagnostic so migration can continue.
That is narrower than ignoring every workspace lookup error. The patch preserves the existing error handling for other failures. Its updated test expects no version-check diagnostics for a nonexistent workspace, then uses a separate case to simulate a server error and expects that check to fail. The tests encode the distinction between a destination not yet created and a service that cannot answer the request.
This specificity matters in an administrative path. Treating every error as evidence of an absent object could allow an operation to proceed after a genuine service failure. Treating every error as fatal prevents the supported creation case. The implementation has enough information to discriminate, because the client library exposes a particular resource-not-found error.
The correction also leaves compatibility enforcement meaningful for an existing destination. There is no claim in the patch that version checks are unnecessary in general. Its reasoning is about the workspace being created. That is the scope in which the absence of a version setting is expected.
Initialization includes state administration
The versioned init documentation describes backend initialization as one of the command's separate responsibilities. Rerunning it after backend settings change can prompt for confirmation of workspace-state migration. The command therefore performs more than downloading modules and providers.
That documentation also distinguishes reconfiguration from migration. The -reconfigure option disregards existing backend configuration and prevents migration of existing state. It is not an equivalent expression of the operation repaired here. Someone who intends to move state needs the migration path to complete, including the legitimate creation of the destination workspace.
Hosted state and hosted execution are separate capabilities too. The remote backend can store state while operations run locally, or run plans and applies in Terraform Cloud. Successful state migration does not by itself configure every requirement of a remote run. The backend documentation recommends creating workspaces in advance when they need variable values or a specific Terraform version for remote operations.
I find that separation useful because it keeps the patch's promise concrete. Version 0.14.9 repairs migration into a destination that initialization is allowed to create. It does not claim that copying state supplies the variables or execution settings required by the configuration. The absent-workspace case can now proceed to creation, while an actual lookup failure still produces an error.