hashicorp/terraform · error

error loading variables

Error message

error loading variables: %w

What it means

After the workspace is loaded, the backend calls Variables.ListAll to fetch Terraform-category variables for remote execution. ErrResourceNotFound is intentionally swallowed (a workspace with no variables is fine); any OTHER error is wrapped here. This path is skipped entirely for Local execution-mode workspaces, so it only fires for Remote execution mode.

Solutions

  1. Ensure the token has at least 'Read Variables' permission on the workspace (team token or user token with appropriate team access).
  2. Retry — 429/5xx from TFC are typically transient; add a short backoff.
  3. If using a service-limited token, verify it is not scoped to a team that lacks variable access.
  4. Check TFC status and the organization's API rate-limit usage.
Defensive patterns

Strategy: retry

Validate before calling

// Confirm token can list variables before plan
vars, err := c.Variables.ListAll(ctx, wsID, nil)
if err != nil && err != tfe.ErrResourceNotFound { return err }

Try / catch

// Retry transient 429/5xx on Variables.ListAll
var v *tfe.VariableList
err := retryOnHTTP(5, func() error {
    var e error
    v, e = c.Variables.ListAll(ctx, wsID, nil)
    if e == tfe.ErrResourceNotFound { e = nil }
    return e
})

Prevention

When it happens

Trigger: b.client.Variables.ListAll(ctx, remoteWorkspaceID, nil) returns an error that is NOT tfe.ErrResourceNotFound: 401/403 (token lacks read-vars scope), 429 rate limit, 5xx server error, or network failure mid-pagination.

Common situations: Team API token used for `terraform plan/apply` lacks permission to read workspace variables; TFC under load returning 429; transient API outage; the workspace was deleted between fetchWorkspace and ListAll.

Related errors


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

Appendix: 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 d32a084675)