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

  1. Read the embedded error body for the HTTP status code: re-login for 401, back off for 429, contact admin for 5xx.
  2. Verify the 'hostname' in the cloud block and that the endpoint is reachable and has a valid certificate.
  3. Re-authenticate with `terraform login` (or refresh TF_TOKEN_* / TFE_TOKEN).
  4. 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

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


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