hashicorp/terraform · error

Error selecting workspace

Error message

Error selecting workspace: %s

What it means

OutputCommand.run retrieves the current workspace via c.Workspace(); any error (workspace file unreadable, workspace does not exist, backend workspace selection failure) is wrapped and the command aborts before loading state. The output command is read-only but still requires a resolvable workspace.

Solutions

  1. Run terraform workspace list to see valid workspaces and switch with terraform workspace select <name>.
  2. Unset TF_WORKSPACE if it refers to a non-existent workspace, or create it with terraform workspace new.
  3. Re-run terraform init after a backend change to refresh workspace state.
  4. Delete a stale .terraform/environment file so the default workspace is used.

Example fix

# before: TF_WORKSPACE=staging but workspace missing
terraform output
# after
terraform workspace new staging   # or select existing
terraform output
Defensive patterns

Strategy: validation

Validate before calling

// Validate the workspace exists before running output.
ws, _ := c.Workspace()
if _, err := backend.Workspaces(); err != nil || !workspaceExists(ws) {
    return fmt.Errorf("workspace %q invalid; run 'terraform workspace list'", ws)
}

Prevention

When it happens

Trigger: terraform output is run; c.Workspace() returns err — TF_WORKSPACE points at a non-existent workspace, the .terraform/environment file is corrupt, or the backend rejects the workspace name.

Common situations: Setting TF_WORKSPACE to a workspace that was never created; running output right after switching backends without terraform init; CI using a workspace name with invalid characters; .terraform/environment left pointing at a deleted workspace.

Related errors


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

Appendix: source

Thrown at internal/command/output.go:81

	}

	// Load the backend
	b, backendDiags := c.backend(".", view)
	diags = diags.Append(backendDiags)
	if backendDiags.HasErrors() {
		return nil, diags
	}

	// Command can be aborted by interruption signals
	ctx, done := c.InterruptibleContext(c.CommandContext())
	defer done()

	// This is a read-only command
	c.ignoreRemoteVersionConflict(b)

	env, err := c.Workspace()
	if err != nil {
		diags = diags.Append(fmt.Errorf("Error selecting workspace: %s", err))
		return nil, diags
	}

	// Get the state
	sMgr, sDiags := b.StateMgr(env)
	if sDiags.HasErrors() {
		diags = diags.Append(fmt.Errorf("Failed to load state: %s", sDiags.Err()))
		return nil, diags
	}

	output, err := sMgr.GetRootOutputValues(ctx)
	if err != nil {
		return nil, diags.Append(err)
	}

	return output, diags
}

View on GitHub (pinned to d32a084675)