hashicorp/terraform · error

resource %s has an unsupported action reason %s

Error message

resource %s has an unsupported action reason %s

What it means

marshalResourceChange switches on rc.ActionReason, enumerating the known ResourceInstanceChangeReason values (replace/delete/read reasons). A reason value outside that set hits the default. This happens when the plan carries an action reason the renderer's switch does not cover.

Source

Thrown at internal/command/jsonplan/plan.go:648

		r.ActionReason = ResourceInstanceDeleteBecauseNoResourceConfig
	case plans.ResourceInstanceDeleteBecauseWrongRepetition:
		r.ActionReason = ResourceInstanceDeleteBecauseWrongRepetition
	case plans.ResourceInstanceDeleteBecauseCountIndex:
		r.ActionReason = ResourceInstanceDeleteBecauseCountIndex
	case plans.ResourceInstanceDeleteBecauseEachKey:
		r.ActionReason = ResourceInstanceDeleteBecauseEachKey
	case plans.ResourceInstanceDeleteBecauseNoModule:
		r.ActionReason = ResourceInstanceDeleteBecauseNoModule
	case plans.ResourceInstanceDeleteBecauseNoMoveTarget:
		r.ActionReason = ResourceInstanceDeleteBecauseNoMoveTarget
	case plans.ResourceInstanceReadBecauseConfigUnknown:
		r.ActionReason = ResourceInstanceReadBecauseConfigUnknown
	case plans.ResourceInstanceReadBecauseDependencyPending:
		r.ActionReason = ResourceInstanceReadBecauseDependencyPending
	case plans.ResourceInstanceReadBecauseCheckNested:
		r.ActionReason = ResourceInstanceReadBecauseCheckNested
	default:
		return r, fmt.Errorf("resource %s has an unsupported action reason %s", r.Address, rc.ActionReason)
	}

	return r, nil
}

// MarshalDeferredResourceChanges converts the provided internal representation
// of DeferredResourceInstanceChangeSrc objects into the public structured JSON
// changes.
// This is public to make testing easier.
func MarshalDeferredResourceChanges(resources []*plans.DeferredResourceInstanceChangeSrc, schemas *terraform.Schemas) ([]DeferredResourceChange, error) {
	var ret []DeferredResourceChange

	var sortedResources []*plans.DeferredResourceInstanceChangeSrc
	sortedResources = append(sortedResources, resources...)
	sort.Slice(sortedResources, func(i, j int) bool {
		if !sortedResources[i].ChangeSrc.Addr.Equal(sortedResources[j].ChangeSrc.Addr) {
			return sortedResources[i].ChangeSrc.Addr.Less(sortedResources[j].ChangeSrc.Addr)
		}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Use a Terraform binary whose version matches or exceeds the one that created the plan.
  2. Report the unhandled action reason value (printed via %s) as a bug.
  3. Regenerate the plan with the rendering binary so the reason set matches.
Defensive patterns

Strategy: validation

Validate before calling

// Reject unrecognized action reasons before marshaling so the failure is
// attributed to version skew up front.
knownReasons := map[plans.ResourceInstanceChangeReason]bool{
    plans.ResourceInstanceChangeNoReason: true,
    plans.ResourceInstanceReplaceBecauseCannotUpdate: true,
    plans.ResourceInstanceReplaceBecauseTainted: true,
    plans.ResourceInstanceReplaceByRequest: true,
    plans.ResourceInstanceReplaceByTriggers: true,
    plans.ResourceInstanceDeleteBecauseNoResourceConfig: true,
    plans.ResourceInstanceDeleteBecauseWrongRepetition: true,
    plans.ResourceInstanceDeleteBecauseCountIndex: true,
    plans.ResourceInstanceDeleteBecauseEachKey: true,
    plans.ResourceInstanceDeleteBecauseNoModule: true,
    plans.ResourceInstanceDeleteBecauseNoMoveTarget: true,
    plans.ResourceInstanceReadBecauseConfigUnknown: true,
    plans.ResourceInstanceReadBecauseDependencyPending: true,
    plans.ResourceInstanceReadBecauseCheckNested: true,
}
for _, rc := range plan.Changes.Resources {
    if !knownReasons[rc.ActionReason] {
        return fmt.Errorf("unsupported action reason %v for %s; version skew?", rc.ActionReason, rc.Addr)
    }
}

Prevention

When it happens

Trigger: The plan was produced by a newer plans package that introduced a new ResourceInstanceChangeReason value not present in this binary's switch at plan.go:618. Reached during resource-change marshaling.

Common situations: Rendering a plan created by a newer Terraform version with an older binary that does not know the new reason; a fork adding a reason without updating jsonplan.

Related errors


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