hashicorp/terraform · error

discarded using the UI or API

Error message

discarded using the UI or API

What it means

Sentinel returned by the remote backend's confirm() poller (backend_common.go:519,527). While the CLI waits at the apply/override prompt, it re-reads the run; if the run's status becomes tfe.RunDiscarded, someone discarded it through the TFC/HCP UI or API. Unlike errRunApproved this is a real abort: the run will not apply, and confirm() maps it to errApplyDiscarded (or errDestroyDiscarded in destroy mode) at backend_common.go:540-545.

Solutions

  1. Re-run terraform apply/destroy to create a fresh run — the discarded run cannot be resumed.
  2. Investigate who/what discarded the run (UI activity log or audit logs) if it was unexpected.
  3. Adjust workspace auto-discard settings or permissions so runs are not discarded under you mid-confirmation.
Defensive patterns

Strategy: try-catch

Type guard

func isRunDiscarded(err error) bool {
    return errors.Is(err, errRunDiscarded) || errors.Is(err, errApplyDiscarded) || errors.Is(err, errDestroyDiscarded)
}

Try / catch

if err := b.confirm(ctx, op, opts, r, "yes"); err != nil {
    if isRunDiscarded(err) {
        // run was discarded server-side; must create a new run to proceed
        return fmt.Errorf("run discarded externally: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: terraform apply/destroy against the remote backend with a pending-confirmation run whose status changes to tfe.RunDiscarded during the confirm() poll loop. Also returned for the 'override' keyword path (backend_common.go:519) when an override-needed run is discarded.

Common situations: A teammate clicks 'Discard run' in the Terraform Cloud UI while the CLI waits. Automation discards long-running speculative runs. A run expires or is auto-discarded by workspace settings while you are at the prompt.

Related errors


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

Appendix: source

Thrown at internal/backend/remote/backend_common.go:29

	"io"
	"math"
	"strconv"
	"strings"
	"time"

	tfe "github.com/hashicorp/go-tfe"

	"github.com/hashicorp/terraform/internal/backend/backendrun"
	"github.com/hashicorp/terraform/internal/logging"
	"github.com/hashicorp/terraform/internal/plans"
	"github.com/hashicorp/terraform/internal/terraform"
)

var (
	errApplyDiscarded   = errors.New("Apply discarded.")
	errDestroyDiscarded = errors.New("Destroy discarded.")
	errRunApproved      = errors.New("approved using the UI or API")
	errRunDiscarded     = errors.New("discarded using the UI or API")
	errRunOverridden    = errors.New("overridden using the UI or API")
)

var (
	backoffMin = 1000.0
	backoffMax = 3000.0

	runPollInterval = 3 * time.Second
)

// backoff will perform exponential backoff based on the iteration and
// limited by the provided min and max (in milliseconds) durations.
func backoff(min, max float64, iter int) time.Duration {
	backoff := math.Pow(2, float64(iter)/5) * min
	if backoff > max {
		backoff = max
	}
	return time.Duration(backoff) * time.Millisecond

View on GitHub (pinned to d32a084675)