hashicorp/terraform · warning

canceled.

Error message

%s canceled.

What it means

During the cost-estimation polling loop, the run's CostEstimate entered tfe.CostEstimateCanceled—someone or something (user, admin, or an auto-cancel policy) aborted the cost estimate. The backend converts this into a fatal error for the run rather than continuing silently.

Solutions

  1. Re-trigger the run and avoid canceling it from the UI mid-flight.
  2. Disable cost estimation for the workspace if it consistently times out.
  3. Coordinate CI and operators so only one source controls a run's lifecycle.
Defensive patterns

Strategy: try-catch

Try / catch

if err := b.checkCostEstimation(ctx, op, r); err != nil {
    if strings.Contains(err.Error(), "canceled") {
        // surface to user / re-trigger the run
        return retryRun(r.ID)
    }
    return err
}

Prevention

When it happens

Trigger: ce.Status transitions to tfe.CostEstimateCanceled while the backend polls the cost estimate. Triggered by a user clicking Cancel in the UI, a run being discarded, or an org-level policy auto-canceling runs.

Common situations: Operator manually cancels a long cost estimate; another teammate discards the run from the UI while CI is waiting; CI timeout in the upstream orchestrator sends a cancel request to TFE.

Related errors


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

Appendix: source

Thrown at internal/cloud/backend_common.go:316

				if i > 0 {
					elapsed = fmt.Sprintf(
						" (%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)

View on GitHub (pinned to d32a084675)