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

  1. Upgrade your terraform CLI to the latest version so its status enum matches the server.
  2. Upgrade/patch the self-hosted TFE install to a version compatible with your CLI, or vice-versa.
  3. 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

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


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