hashicorp/terraform · error
%s returned an unexpected error: %s
Error message
%s returned an unexpected error: %s
What it means
The default branch of fetchWorkspace (backend.go:1343-1349). Any Workspaces.Read error that is neither context.Canceled nor tfe.ErrResourceNotFound is wrapped here as an 'unexpected error' from HCP Terraform / TFE, including the raw error body. This is the catch-all for connectivity, auth (non-404), rate-limit, and server-failure responses.
Source
Thrown at internal/cloud/backend.go:1344
}
func (b *Cloud) fetchWorkspace(ctx context.Context, organization string, workspace string) (*tfe.Workspace, error) {
// Retrieve the workspace for this operation.
w, err := b.client.Workspaces.Read(ctx, organization, workspace)
if err != nil {
switch err {
case context.Canceled:
return nil, err
case tfe.ErrResourceNotFound:
return nil, fmt.Errorf(
"workspace %s not found\n\n"+
fmt.Sprintf("For security, %s returns '404 Not Found' responses for resources\n", b.appName)+
"for resources that a user doesn't have access to, in addition to resources that\n"+
"do not exist. If the resource does exist, please check the permissions of the provided token.",
workspace,
)
default:
err := fmt.Errorf(
"%s returned an unexpected error:\n\n%s",
b.appName,
err,
)
return nil, err
}
}
return w, nil
}
// validWorkspaceEnvVar ensures we have selected a valid workspace using TF_WORKSPACE:
// First, it ensures the workspace specified by TF_WORKSPACE exists in the organization.
// (This is because we deliberately DON'T implicitly create a workspace from TF_WORKSPACE,
// unlike with a workspace specified via `name`.)
// Second, if tags are specified in the configuration, it ensures TF_WORKSPACE belongs to the set
// of available workspaces with those given tags.
func (b *Cloud) validWorkspaceEnvVar(ctx context.Context, organization, workspace string) tfdiags.Diagnostic {View on GitHub (pinned to c9def3e214)
Solutions
- Read the embedded error body for the HTTP status code: re-login for 401, back off for 429, contact admin for 5xx.
- Verify the 'hostname' in the cloud block and that the endpoint is reachable and has a valid certificate.
- Re-authenticate with `terraform login` (or refresh TF_TOKEN_* / TFE_TOKEN).
- Retry after a brief wait for transient server/network errors.
Example fix
// before
cloud { hostname = "tfe.corp" organization = "myorg" workspaces { name = "app" } }
// -> tfe.corp returned an unexpected error: ... 401 Unauthorized
// after: refresh credentials
terraform login # or export TF_TOKEN_app_at_tfe_corp=... Defensive patterns
Strategy: try-catch
Validate before calling
// Health-check the API endpoint and token before the real run.
func apiHealthy(ctx context.Context, c *tfe.Client) bool {
_, err := c.Organizations.Read(ctx, "my-org")
return err == nil
} Try / catch
// Classify the wrapped unexpected error.
err := b.fetchWorkspace(ctx, org, ws)
var apiErr *tfe.Error
if errors.As(err, &apiErr) {
switch apiErr.Status {
case 401: refreshToken()
case 429: backoffRetry()
case 500,502,503: retryWithBackoff()
}
} Prevention
- Validate the hostname and TLS cert in the cloud block.
- Refresh tokens before they expire; use `terraform login`.
- Add a connectivity pre-check in CI before running plan/apply.
When it happens
Trigger: Workspaces.Read returns an error not matching context.Canceled or tfe.ErrResourceNotFound. Examples: 401 invalid token, 500/502 server error, TLS/DNS failure, 429 rate limit, request timeout.
Common situations: Expired or revoked API token (401). TFE maintenance window or outage. Custom hostname with a bad TLS certificate. DNS misconfiguration for the 'hostname' in the cloud block. Aggressive automation hitting rate limits.
Related errors
- operation timed out
- {joined API error payload}
- {r.Status}
- a network issue prevented cloud configuration; %w
- organization %q at host %s not found. Please ensure that th
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/1d586be51b1c9e85.
Report an issue: GitHub.