hashicorp/terraform · error

action %s has config values with unsupported marks: %v

Error message

action %s has config values with unsupported marks: %v

What it means

After stripping both sensitive and ephemeral marks from the action config value, any remaining marks are unrecognized by the renderer. Only those two mark kinds are handled, so leftover marks indicate a mark type the JSON format cannot faithfully represent, and serialization is aborted.

Source

Thrown at internal/command/jsonplan/action_invocations.go:165

			ai.InvokeActionTrigger.CallingResourceAddress = at.CallingResourceAddr.String()
		}
	default:
		return ai, fmt.Errorf("unsupported action trigger type: %T", at)
	}

	var config []byte
	var sensitive []byte
	var unknown []byte

	if actionDec.ConfigValue != cty.NilVal {
		unmarkedValue, pvms := actionDec.ConfigValue.UnmarkDeepWithPaths()
		sensitivePaths, otherMarks := marks.PathsWithMark(pvms, marks.Sensitive)
		ephemeralPaths, otherMarks := marks.PathsWithMark(otherMarks, marks.Ephemeral)
		if len(ephemeralPaths) > 0 {
			return ai, fmt.Errorf("action %s has ephemeral config values, which are not supported in action invocations", action.Addr)
		}
		if len(otherMarks) > 0 {
			return ai, fmt.Errorf("action %s has config values with unsupported marks: %v", action.Addr, otherMarks)
		}

		unknownValue := unknownAsBool(unmarkedValue)
		unknown, err = ctyjson.Marshal(unknownValue, unknownValue.Type())
		if err != nil {
			return ai, err
		}

		configValue := omitUnknowns(unmarkedValue)
		config, err = ctyjson.Marshal(configValue, configValue.Type())
		if err != nil {
			return ai, err
		}

		sensitivePaths = append(sensitivePaths, schema.ConfigSchema.SensitivePaths(unmarkedValue, nil)...)
		cs := jsonstate.SensitiveAsBool(marks.MarkPaths(unmarkedValue, marks.Sensitive, sensitivePaths))
		sensitive, err = ctyjson.Marshal(cs, cs.Type())
		if err != nil {

View on GitHub (pinned to c9def3e214)

Solutions

  1. Inspect the %v output to identify which mark is present, then strip it before marshaling or add a handler in action_invocations.go:159.
  2. Use a Terraform build consistent with the plan artifact (no version skew).
  3. Report as a bug if the mark is a standard Terraform mark the renderer should support.
Defensive patterns

Strategy: validation

Validate before calling

// After stripping sensitive and ephemeral, fail fast on any remaining mark.
for _, a := range plan.Changes.ActionInvocations {
    sch := schemas.ActionTypeConfig(a.ProviderAddr.Provider, a.Addr.Action.Action.Type)
    dec, err := a.Decode(&sch)
    if err != nil || dec.ConfigValue == cty.NilVal {
        continue
    }
    unmarked, pvms := dec.ConfigValue.UnmarkDeepWithPaths()
    _, other := marks.PathsWithMark(pvms, marks.Sensitive)
    _, other = marks.PathsWithMark(other, marks.Ephemeral)
    if len(other) > 0 {
        return fmt.Errorf("action %s carries unsupported marks: %v", a.Addr, other)
    }
    _ = unmarked
}

Prevention

When it happens

Trigger: len(otherMarks) > 0 after marks.PathsWithMark(pvms, marks.Sensitive) and then marks.PathsWithMark(otherMarks, marks.Ephemeral). A custom or newly introduced cty mark is attached to the decoded ConfigValue.

Common situations: A custom Terraform fork adding a new mark kind; a plan from a newer version that introduced a mark this binary does not know about; experimental/internal marks leaking into action config.

Related errors


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