hashicorp/terraform · error

hard failed.

Error message

%s hard failed.

What it means

Returned when a policy check's status is tfe.PolicyHardFailed. Hard-mandatory policy violations cannot be overridden by any user; the run is permanently blocked until the configuration complies. There is no override path, unlike soft failures.

Solutions

  1. Read the policy failure detail in the TFC/TFE UI to see which rule failed and why.
  2. Modify the Terraform configuration to satisfy the hard-mandatory policy.
  3. If the policy itself is wrong, change its enforcement level (requires policy admin) - but do not weaken governance lightly.
  4. Re-plan once the configuration complies.
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight policy simulation is not directly available, but you can static-check
// configs against known-hard rules before pushing.
// Use 'terraform validate' + custom Conftest/OPA checks mirroring hard-mandatory rules.

Try / catch

// Hard fails are non-recoverable; do not retry, route to the config owner.
if pc.Status == tfe.PolicyHardFailed {
    return fmt.Errorf("hard-mandatory policy failed; config must be changed - no override possible")
}

Prevention

When it happens

Trigger: pc.Status == tfe.PolicyHardFailed during checkPolicy. A policy enforced at 'hard-mandatory' level evaluated to false (e.g. disallowed instance type, forbidden region, missing required tags).

Common situations: Config violates a governance policy (banned provider, public S3 bucket, non-approved AMI); policy enforcement was recently tightened; new policy set added to the workspace.

Related errors


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

Appendix: source

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

					line = append(line, l...)
				}

				if next || len(line) > 0 {
					b.CLI.Output(b.Colorize().Color(string(line)))
				}
			}
		}

		switch pc.Status {
		case tfe.PolicyPasses:
			if (r.HasChanges && op.Type == backendrun.OperationTypeApply || i < len(r.PolicyChecks)-1) && b.CLI != nil {
				b.CLI.Output("\n------------------------------------------------------------------------")
			}
			continue
		case tfe.PolicyErrored:
			return fmt.Errorf("%s errored.", msgPrefix)
		case tfe.PolicyHardFailed:
			return fmt.Errorf("%s hard failed.", msgPrefix)
		case tfe.PolicySoftFailed:
			runURL := fmt.Sprintf(runHeaderErr, b.hostname, b.organization, op.Workspace, r.ID)

			if op.Type == backendrun.OperationTypePlan || op.UIOut == nil || op.UIIn == nil ||
				!pc.Actions.IsOverridable || !pc.Permissions.CanOverride {
				return fmt.Errorf("%s soft failed.\n%s", msgPrefix, runURL)
			}

			if op.AutoApprove {
				if _, err = b.client.PolicyChecks.Override(stopCtx, pc.ID); err != nil {
					return generalError(fmt.Sprintf("Failed to override policy check.\n%s", runURL), err)
				}
			} else {
				opts := &terraform.InputOpts{
					Id:          "override",
					Query:       "\nDo you want to override the soft failed policy check?",
					Description: "Only 'override' will be accepted to override.",
				}

View on GitHub (pinned to d32a084675)