hashicorp/terraform · error

Invalid Task stage status: %s

Error message

Invalid Task stage status: %s 

What it means

Returned by runTaskStage polling when stage.Status does not match any case in the switch (passed, failed, canceled, errored, awaiting_override, unreachable, pending, running). It signals a forward-incompatibility: the API returned a TaskStageStatus value the client does not know about.

Source

Thrown at internal/cloud/backend_taskStages.go:163

			if e != nil {
				errs = e
			}
			if ok {
				return true, nil
			}
			cont, err := b.processStageOverrides(ctx, output, stage.ID)
			if err != nil {
				errs = errors.Join(errs, err)
			} else {
				if b.CLI != nil {
					b.CLI.Output("------------------------------------------------------------------------")
				}
				return cont, nil
			}
		case tfe.TaskStageUnreachable:
			return false, nil
		default:
			return false, fmt.Errorf("Invalid Task stage status: %s ", stage.Status)
		}
		return false, errs
	})
}

func processSummarizers(ctx *IntegrationContext, output IntegrationOutputWriter, stage *tfe.TaskStage, summarizers []taskStageSummarizer, errs error) (bool, error) {
	for _, s := range summarizers {
		cont, msg, err := s.Summarize(ctx, output, stage)
		if err != nil {
			errs = errors.Join(errs, err)
			break
		}

		if !cont {
			continue
		}

		// cont is true and we must continue to poll

View on GitHub (pinned to c9def3e214)

Solutions

  1. Upgrade the Terraform CLI to a version whose go-tfe knows the new status value.
  2. Downgrade/avoid the server feature that produces the new status until the client is upgraded.
  3. Retry once the run settles into a known status.

Example fix

// before (older client, unknown status from server)
default:
    return false, fmt.Errorf("Invalid Task stage status: %s ", stage.Status)
// after: upgrade Terraform CLI so the switch has a case for the new status
Defensive patterns

Strategy: validation

Validate before calling

// Refuse to poll task stages from an older client against a newer server.
if _, known := knownTaskStageStatuses[stage.Status]; !known {
    return fmt.Errorf("client too old for task status %q; upgrade Terraform", stage.Status)
}

Type guard

var knownTaskStageStatuses = map[tfe.TaskStageStatus]struct{}{
    tfe.TaskStagePending: {}, tfe.TaskStageRunning: {}, tfe.TaskStagePassed: {},
    tfe.TaskStageFailed: {}, tfe.TaskStageCanceled: {}, tfe.TaskStageErrored: {},
    tfe.TaskStageAwaitingOverride: {}, tfe.TaskStageUnreachable: {},
}

Prevention

When it happens

Trigger: Polling a task stage whose status enum is newer than the Terraform binary's go-tfe library version. Reached via the default branch of the switch.

Common situations: Older Terraform binary talking to a newer TFE/HCP backend that introduced a new task stage status; version skew between client and server.

Related errors


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