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
- Grant the token's team 'Read Variables' (or broader) permission on the workspace.
- Retry on transient failures; unwrap %w to inspect the status.
- 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
- Grant the token's team 'Read Variables' permission on the workspace.
- Retry transient variable-API failures; unwrap %w for the status.
- Use the AllowUnsetVariables path when variables aren't needed for a local op.
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
- error finding remote workspace: %w
- Error creating workspace %s: %v
- failed to retrieve project %s: %v
- Attempted to find configured project %s but was unable to.
- failed to create project %s: %v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/39d818c854d10501.
Report an issue: GitHub.