hashicorp/terraform · error
%s canceled.
Error message
%s canceled.
What it means
In costEstimate(), when the cost-estimate sub-resource's status becomes tfe.CostEstimateCanceled. This means the cost estimation was canceled (typically because the parent run was canceled via the UI or API while estimation was pending/queued), so the polling loop returns this error to abort the operation.
Source
Thrown at internal/backend/remote/backend_common.go:366
if i > 0 {
elapsed = fmt.Sprintf(
" (%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)View on GitHub (pinned to c9def3e214)
Solutions
- Re-run the plan/apply — the cancellation was external and the next run will get a fresh cost estimate.
- Avoid canceling runs in the UI while a local CLI stream is attached.
- If cancellations are automated, review the automation triggering them.
Defensive patterns
Strategy: try-catch
Type guard
func isCostCanceled(s tfe.CostEstimateStatus) bool {
return s == tfe.CostEstimateCanceled
} Try / catch
if err := b.costEstimate(stopCtx, cancelCtx, op, r); err != nil {
if strings.Contains(err.Error(), "canceled") {
// external cancel of cost estimate -> surface, invite re-run
}
return err
} Prevention
- Avoid canceling runs in the UI while a CLI stream is attached.
- Review automation that auto-discards queued runs.
- Document that a canceled cost estimate requires re-running the plan.
When it happens
Trigger: costEstimate() polls CostEstimates.Read; ce.Status == tfe.CostEstimateCanceled. Usually the parent run was discarded/canceled by a user or automation in the HCP/TFE UI while cost estimation was still running.
Common situations: Someone clicked 'Discard run' or canceled via API during a plan that includes cost estimation; a run exceeded a timeout and was auto-canceled; concurrent operations where one cancel cascades.
Related errors
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/cc049afadde28bd0.
Report an issue: GitHub.