hashicorp/terraform · error

Task Stage ' ': .

Error message

Task Stage '%s': %s.

What it means

waitTaskStage polls a TFC Task Stage; when its status reaches Canceled, Errored, or Failed the polling stops with this error naming the stage ID and its terminal status. This represents a configured Run Task (custom or built-in) that ran during plan/apply and did not pass.

Solutions

  1. Open the stage ID in the TFC/TFE UI to see the task-result detail and address the root cause.
  2. If the task endpoint is a custom service, verify it is up, returning 200, and within the allowed timeout.
  3. For non-mandatory tasks, switch the enforcement level from 'mandatory' so failures don't block.
  4. Override the stage on the TFC UI if the failure is spurious and policy allows overrides.
Defensive patterns

Strategy: try-catch

Validate before calling

// Inspect task results at the stage before failing the run
stage, _ := c.TaskStages.Read(ctx, stageID, opts)
for _, r := range stage.TaskResults { if r.Status == "failed" { log.Println(r.Message) } }

Type guard

func isTerminalTaskFailure(s tfe.TaskStageStatus) bool {
    switch s {
    case tfe.TaskStageCanceled, tfe.TaskStageErrored, tfe.TaskStageFailed:
        return true
    }
    return false
}

Try / catch

// Stop polling on terminal failure; surface stage ID for UI follow-up
if isTerminalTaskFailure(stage.Status) {
    return fmt.Errorf("task stage %s ended %s; see TFC UI", stage.ID, stage.Status)
}

Prevention

When it happens

Trigger: stage.Status is tfe.TaskStageCanceled, tfe.TaskStageErrored, or tfe.TaskStageFailed: the run task endpoint returned an error, the task was canceled, or its exit/evaluation failed during the stage.

Common situations: A mandatory/preventive run task (e.g. policy-as-code, cost estimation, custom webhook task) failed and blocked the run; task integration endpoint (external service) was unreachable; task was manually canceled in the TFC UI.

Related errors


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

Appendix: source

Thrown at internal/backend/remote/backend_taskStages.go:45

		options := tfe.TaskStageReadOptions{
			Include: []tfe.TaskStageIncludeOpt{tfe.TaskStageTaskResults, tfe.PolicyEvaluationsTaskResults},
		}
		stage, err := b.client.TaskStages.Read(ctx.StopContext, stageID, &options)
		if err != nil {
			return false, generalError("Failed to retrieve task stage", err)
		}

		switch stage.Status {
		case tfe.TaskStagePending:
			// Waiting for it to start
			return true, nil
		case tfe.TaskStageRunning:
			// not a terminal status so we continue to poll
			return true, nil
		case tfe.TaskStagePassed:
			return false, nil
		case tfe.TaskStageCanceled, tfe.TaskStageErrored, tfe.TaskStageFailed:
			return false, fmt.Errorf("Task Stage '%s': %s.", stage.ID, stage.Status)
		case tfe.TaskStageAwaitingOverride:
			return false, fmt.Errorf("Task Stage '%s' awaiting override.", stage.ID)
		case tfe.TaskStageUnreachable:
			return false, nil
		default:
			return false, fmt.Errorf("Task stage '%s' has invalid status: %s", stage.ID, stage.Status)
		}
	})
}

View on GitHub (pinned to d32a084675)