hashicorp/terraform · error

Unknown or unexpected cost estimate state: %s

Error message

Unknown or unexpected cost estimate state: %s

What it means

The default case of the cost-estimate status switch (backend_common.go:318). It fires when ce.Status does not match any of the handled tfe.CostEstimate* constants (Finished, Pending, Queued, SkippedDueToTargeting, Errored, Canceled). This indicates a client/server version skew where the server emitted a new status value the local go-tfe library does not understand.

Source

Thrown at internal/cloud/backend_common.go:318

						" (%s elapsed)", current.Sub(started).Truncate(30*time.Second))
				}
				b.CLI.Output(b.Colorize().Color("[bold]" + 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("[bold]" + 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 *Cloud) 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 b.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 the local Terraform CLI to a version whose go-tfe dependency recognizes the new status.
  2. Downgrade or stabilize the TFE server to a release compatible with your CLI.
  3. Report the unknown status string (in the error message) to Terraform maintainers if versions are current.

Example fix

// before: terraform 1.5.x against bleeding-edge HCP Terraform
// -> Unknown or unexpected cost estimate state: "custom_state"
// after: upgrade CLI
terraform version  # confirm, then upgrade to latest stable
Defensive patterns

Strategy: validation

Validate before calling

// Guard against unknown statuses by pinning compatible versions.
func knownCostEstimateStatus(s tfe.CostEstimateStatus) bool {
    switch s {
    case tfe.CostEstimateFinished, tfe.CostEstimatePending, tfe.CostEstimateQueued,
         tfe.CostEstimateSkippedDueToTargeting, tfe.CostEstimateErrored, tfe.CostEstimateCanceled:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: The TFE/HCP server is newer than the bundled go-tfe constants in the local Terraform binary, returning a cost-estimate status string outside the known set. Encountered mid-poll in the switch at backend_common.go:265.

Common situations: Using an older Terraform CLI against a much newer HCP Terraform / TFE that introduced a new cost-estimate lifecycle state. Pre-release/unstable server features.

Related errors


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