hashicorp/terraform · error

error loading variables: %w

Error message

error loading variables: %w

What it means

In LocalRun(), b.client.Variables.ListAll(remoteWorkspaceID, nil) returned an error that is not tfe.ErrResourceNotFound. The code explicitly tolerates a 404 (older TFE without the variables endpoint) but any other failure — auth, network, server error — surfaces as 'error loading variables'. Only reached for non-local-execution workspaces.

Source

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

		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 {
						if _, ok := op.Variables[v.Key]; !ok {
							op.Variables[v.Key] = &remoteStoredVariableValue{
								definition: v,
							}
						}
					}
				}
			}
		}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Grant the token's team 'Read Variables' (or broader) permission on the workspace.
  2. Retry on transient failures; unwrap %w to inspect the status.
  3. If variables aren't required for this local operation, consider stubbing (AllowUnsetVariables) to skip this path.
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify variable-read permission before listing.
func canReadVars(w *tfe.Workspace) bool {
    return w != nil && w.Permissions != nil && w.Permissions.CanReadVariable
}

Type guard

func isNotFound(err error) bool { return errors.Is(err, tfe.ErrResourceNotFound) }

Try / catch

vars, err := b.client.Variables.ListAll(ctx, id, nil)
if err != nil && !errors.Is(err, tfe.ErrResourceNotFound) {
    return fmt.Errorf("error loading variables: %w", err)
}

Prevention

When it happens

Trigger: LocalRun() lists workspace variables to inject them into a local plan/apply; ListAll fails with a non-404 error: token lacks variable-read permission, 5xx, network failure, or the variables API rejected the call.

Common situations: Token's team lacks 'Read Variables' permission on the workspace; transient API error; self-hosted TFE with a variables-service issue; the workspace has many variables and pagination/timeout occurs.

Related errors


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