hashicorp/terraform · error

error loading workspace: %w

Error message

error loading workspace: %w

What it means

In LocalRun(), b.fetchWorkspace(context.Background(), b.organization, op.Workspace) failed. This second workspace fetch (after getRemoteWorkspaceID) is done specifically to read w.ExecutionMode and decide whether to pull variables. It can return the same 'workspace not found' / 'unexpected error' messages as error 403/404, wrapped here under 'error loading workspace'.

Source

Thrown at internal/backend/remote/backend_context.go:108

	if op.AllowUnsetVariables {
		// If we're not going to use the variables in an operation we'll be
		// more lax about them, stubbing out any unset ones as unknown.
		// This gives us enough information to produce a consistent context,
		// but not enough information to run a real operation (plan, apply, etc)
		ret.PlanOpts.SetVariables = stubAllVariables(op.Variables, rootMod.Variables)
	} else {
		// The underlying API expects us to use the opaque workspace id to request
		// variables, so we'll need to look that up using our organization name
		// and workspace name.
		remoteWorkspaceID, err := b.getRemoteWorkspaceID(context.Background(), op.Workspace)
		if err != nil {
			diags = diags.Append(fmt.Errorf("error finding remote workspace: %w", err))
			return nil, nil, diags
		}

		w, err := b.fetchWorkspace(context.Background(), b.organization, op.Workspace)
		if err != nil {
			diags = diags.Append(fmt.Errorf("error loading workspace: %w", err))
			return nil, nil, diags
		}

		if isLocalExecutionMode(w.ExecutionMode) {
			log.Printf("[TRACE] skipping retrieving variables from workspace %s/%s (%s), workspace is in Local Execution mode", remoteWorkspaceName, b.organization, remoteWorkspaceID)
		} else {
			log.Printf("[TRACE] backend/remote: retrieving variables from workspace %s/%s (%s)", remoteWorkspaceName, b.organization, remoteWorkspaceID)
			tfeVariables, err := b.client.Variables.ListAll(context.Background(), remoteWorkspaceID, nil)
			if err != nil && err != tfe.ErrResourceNotFound {
				diags = diags.Append(fmt.Errorf("error loading variables: %w", err))
				return nil, nil, diags
			}
			if tfeVariables != nil {
				if op.Variables == nil {
					op.Variables = make(map[string]arguments.UnparsedVariableValue)
				}
				for _, v := range tfeVariables.Items {
					if v.Category == tfe.CategoryTerraform {

View on GitHub (pinned to c9def3e214)

Solutions

  1. Unwrap the %w to see whether it's the 'workspace not found' (403-shape) or 'unexpected error' (404-shape) message and follow that error's guidance.
  2. Confirm workspace name, org, and token read access are stable.
  3. Retry; transient failures between the two fetches indicate a flaky connection.
Defensive patterns

Strategy: validation

Validate before calling

// Precheck execution-mode fetch once and reuse, avoiding a second failing call.
w, err := b.fetchWorkspace(ctx, b.organization, op.Workspace)
if err != nil { return err }

Type guard

func isLocalMode(w *tfe.Workspace) bool { return isLocalExecutionMode(w.ExecutionMode) }

Try / catch

w, err := b.fetchWorkspace(context.Background(), b.organization, op.Workspace)
if err != nil {
    return fmt.Errorf("error loading workspace: %w", err)
}

Prevention

When it happens

Trigger: LocalRun() calls fetchWorkspace() to check execution mode; it errors — either tfe.ErrResourceNotFound (wrapped into the 'workspace not found' 403-style message) or any other error (wrapped into the 'unexpected error' 404-style message). Note this uses context.Background(), so context.Canceled won't short-circuit it.

Common situations: A workspace that was readable a moment earlier (for getRemoteWorkspaceID) now fails — rare race; more commonly the same misconfiguration as 417 but surfaced at the execution-mode step; token permissions changed between calls.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/409683487110dfc6. Report an issue: GitHub.