hashicorp/terraform · error
%s soft failed. %s
Error message
%s soft failed. %s
What it means
In checkPolicy(), when pc.Status == tfe.PolicySoftFailed AND the run cannot be overridden in the current context: it's a plan operation, or there is no interactive UI (UIIn/UIOut nil), or the policy check is not overridable (pc.Actions.IsOverridable false) or the token lacks override permission (pc.Permissions.CanOverride false). A soft failure is overridable in principle, but not from this code path, so it surfaces as an error with a run URL.
Source
Thrown at internal/backend/remote/backend_common.go:451
}
}
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.",
}
err = b.confirm(stopCtx, op, opts, r, "override")
if err != nil && err != errRunOverridden {
return fmt.Errorf("Failed to override: %w\n%s\n", err, runURL)
}
if err != errRunOverridden {View on GitHub (pinned to c9def3e214)
Solutions
- Follow the run URL in the message to override (or discard) the soft failure in the HCP/TFE UI.
- Fix the configuration to satisfy the policy so no override is needed.
- Grant the token's team the 'Override Soft Policy' permission AND run apply (not plan) interactively so the override prompt appears next time.
- Use `terraform apply -auto-approve` which takes the auto-override branch (line 454) if permissions allow.
Defensive patterns
Strategy: try-catch
Validate before calling
// Only attempt override path when permissions + apply context allow it.
func canOverrideHere(op *backendrun.Operation, pc *tfe.PolicyCheck) bool {
return op.Type != backendrun.OperationTypePlan &&
op.UIIn != nil && op.UIOut != nil &&
pc.Actions.IsOverridable && pc.Permissions.CanOverride
} Type guard
func isSoftFailed(s tfe.PolicyStatus) bool {
return s == tfe.PolicySoftFailed
} Try / catch
if err := b.checkPolicy(stopCtx, cancelCtx, op, r); err != nil {
if strings.Contains(err.Error(), "soft failed") {
// direct user to the run URL in the message to override via UI
}
return err
} Prevention
- Grant the token's team 'Override Soft Policy' permission if overrides are expected.
- Don't rely on plan-time override prompts — plans never offer override; use apply.
- Fix soft-policy violations in config when possible to avoid needing override.
- Run interactively (with UIIn/UIOut) so the override prompt can appear.
When it happens
Trigger: A soft-mandatory policy fails during: a `plan` (op.Type == OperationTypePlan, no override offered for plans), a non-interactive run (no terminal/UIIn), or when the policy/token disallows override. The user is given the run URL to act in the UI.
Common situations: Running `terraform plan` remotely where a soft policy fails (plans never prompt to override); running in CI with no interactive UI so the override prompt can't appear; the token's team lacks 'Override soft policy' permission.
Related errors
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/7397cc94ccdb7ff3.
Report an issue: GitHub.