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
- Ensure the token has at least 'Read Variables' permission on the workspace (team token or user token with appropriate team access).
- Retry — 429/5xx from TFC are typically transient; add a short backoff.
- If using a service-limited token, verify it is not scoped to a team that lacks variable access.
- 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
- Grant the run token 'Read Variables' on the workspace.
- Use workspace-scoped tokens rather than org-wide tokens to reduce blast radius.
- Remember variables are only fetched for Remote execution-mode workspaces.
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
- error deleting workspace
- error loading variables
- Error retrieving state
- error uploading state
- approved using the UI or API
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)