hashicorp/terraform · error
Unknown or unexpected cost estimate state: %s
Error message
Unknown or unexpected cost estimate state: %s
What it means
The default branch of costEstimate()'s status switch: the cost-estimate returned a status string not matched by any known case (Finished, Pending, Queued, SkippedDueToTargeting, Errored, Canceled). This indicates the go-tfe client / terraform version is out of date relative to the server, which introduced a new cost-estimate status.
Source
Thrown at internal/backend/remote/backend_common.go:368
" (%s elapsed)", current.Sub(started).Truncate(30*time.Second))
}
b.CLI.Output(b.Colorize().Color(msgPrefix + ":\n"))
b.CLI.Output(b.Colorize().Color("Waiting for cost estimate to complete..." + elapsed + "\n"))
}
continue
case tfe.CostEstimateSkippedDueToTargeting:
b.CLI.Output(b.Colorize().Color(msgPrefix + ":\n"))
b.CLI.Output("Not available for this plan, because it was created with the -target option.")
b.CLI.Output("\n------------------------------------------------------------------------")
return nil
case tfe.CostEstimateErrored:
b.CLI.Output(msgPrefix + " errored.\n")
b.CLI.Output("\n------------------------------------------------------------------------")
return nil
case tfe.CostEstimateCanceled:
return fmt.Errorf("%s canceled.", msgPrefix)
default:
return fmt.Errorf("Unknown or unexpected cost estimate state: %s", ce.Status)
}
}
}
func (b *Remote) checkPolicy(stopCtx, cancelCtx context.Context, op *backendrun.Operation, r *tfe.Run) error {
if b.CLI != nil {
b.CLI.Output("\n------------------------------------------------------------------------\n")
}
for i, pc := range r.PolicyChecks {
// Read the policy check logs. This is a blocking call that will only
// return once the policy check is complete.
logs, err := b.client.PolicyChecks.Logs(stopCtx, pc.ID)
if err != nil {
return generalError("Failed to retrieve policy check logs", err)
}
reader := bufio.NewReaderSize(logs, 64*1024)
// Retrieve the policy check to get its current status.View on GitHub (pinned to c9def3e214)
Solutions
- Upgrade your terraform CLI to the latest version so its status enum matches the server.
- Upgrade/patch the self-hosted TFE install to a version compatible with your CLI, or vice-versa.
- Report the unknown status value (shown in the message) if it persists on the latest CLI.
Defensive patterns
Strategy: type-guard
Type guard
var knownCostStatuses = map[tfe.CostEstimateStatus]bool{
tfe.CostEstimateFinished: true, tfe.CostEstimatePending: true,
tfe.CostEstimateQueued: true, tfe.CostEstimateErrored: true,
tfe.CostEstimateCanceled: true, tfe.CostEstimateSkippedDueToTargeting: true,
}
func isKnownCostStatus(s tfe.CostEstimateStatus) bool { return knownCostStatuses[s] } Prevention
- Keep terraform CLI on the latest release to match new server-side statuses.
- Align self-hosted TFE and CLI versions.
- Report unknown statuses that persist on the latest CLI as a bug.
When it happens
Trigger: A newer HCP Terraform / TFE server returns a CostEstimate status value that this build of terraform's switch statement doesn't know about; the value is rendered via %s in the message.
Common situations: Terraform CLI is older than the TFE/HCP server which added a new cost-estimate lifecycle state; using a self-hosted TFE on a newer version than the bundled go-tfe supports.
Related errors
- Unknown or unexpected policy state: %s
- Remote workspace Terraform version %q does not match local T
- The "remote" backend does not support the %q operation.
- %s canceled.
- error uploading state in compatibility mode: %v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/07b015591d1524c0.
Report an issue: GitHub.