hashicorp/terraform · error

Failed to set new workspace

Error message

Failed to set new workspace: %s

What it means

Returned during single-to-single migration when the destination workspace cannot be made the active workspace after the destination state manager is constructed. The error is wrapped from `m.SetWorkspace(opts.destinationWorkspace)` and surfaced as a tuple `(nil, error)` from an immediately-invoked closure.

Solutions

  1. Ensure the working directory is writable by the user running `terraform init`.
  2. Validate `opts.destinationWorkspace` is a legal workspace name for the destination backend.
  3. Retry after fixing filesystem permissions on `.terraform/terraform.tfstate` and the workspace marker.
Defensive patterns

Strategy: try-catch

Validate before calling

# Ensure the working directory and workspace marker are writable.
touch .terraform/.workspace-write-test && rm .terraform/.workspace-write-test \
  || echo "working dir not writable by $(whoami)"
terraform init

Try / catch

# Fail with an actionable message when workspace selection breaks:
if ! terraform init >/tmp/init.log 2>&1; then
  grep -q 'Failed to set new workspace' /tmp/init.log \
    && { echo 'Check .terraform/ write perms and workspace name validity' >&2; exit 2; }
  cat /tmp/init.log; exit 1
fi

Prevention

When it happens

Trigger: Fires inside the `func() (statemgr.Full, error) {...}()` closure in `backendMigrateState_s_s` when the current workspace equals `backend.DefaultStateName` and `m.SetWorkspace(opts.destinationWorkspace)` returns an error — typically because the local workspace metadata store cannot persist the selection.

Common situations: A read-only working directory, filesystem permissions on the local `.terraform/` workspace marker, or an invalid destination workspace name rejected by the local workspace backend.

Related errors


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

Appendix: source

Thrown at internal/command/meta_backend_migrate.go:324

					return nil, err
				}

				// Update the name of the destination state.
				opts.destinationWorkspace = name

				destinationState, sDiags := opts.Destination.StateMgr(opts.destinationWorkspace)
				if sDiags.HasErrors() {
					return nil, sDiags.Err()
				}

				// Ignore invalid workspace name as it is irrelevant in this context.
				workspace, _ := m.Workspace()

				// If the currently selected workspace is the default workspace, then set
				// the named workspace as the new selected workspace.
				if workspace == backend.DefaultStateName {
					if err := m.SetWorkspace(opts.destinationWorkspace); err != nil {
						return nil, fmt.Errorf("Failed to set new workspace: %s", err)
					}
				}

				return destinationState, nil
			}()
		} else {
			// For any other error, return it immediately to avoid nil pointer dereference
			return fmt.Errorf(strings.TrimSpace(
				errMigrateSingleLoadDefault), opts.DestinationType, dstWord, sDiags.Err())
		}
	}
	if err != nil {
		return fmt.Errorf(strings.TrimSpace(
			errMigrateSingleLoadDefault), opts.DestinationType, err)
	}
	if err := destinationState.RefreshState(); err != nil {
		return fmt.Errorf(strings.TrimSpace(
			errMigrateSingleLoadDefault), opts.DestinationType, err)

View on GitHub (pinned to d32a084675)