opentofu/opentofu · error
ephemeral resource %q detected in the plan. This is an error
Error message
ephemeral resource %q detected in the plan. This is an error in OpenTofu
What it means
While marshaling planned values for `tofu show -json` (jsonplan.marshalPlanResources), a resource change whose address has EphemeralResourceMode is refused. Ephemeral resources (managed via ephemeral blocks) are never persisted nor included in planned-change output, so encountering one in the changes set violates a core invariant — the message itself states 'This is an error in OpenTofu'.
Source
Thrown at internal/command/jsonplan/values.go:208
if r.Action == plans.Delete {
continue
}
resource := Resource{
Address: r.Addr.String(),
Type: r.Addr.Resource.Resource.Type,
Name: r.Addr.Resource.Resource.Name,
ProviderName: r.ProviderAddr.Provider.String(),
Index: r.Addr.Resource.Key,
}
switch r.Addr.Resource.Resource.Mode {
case addrs.ManagedResourceMode:
resource.Mode = "managed"
case addrs.DataResourceMode:
resource.Mode = "data"
case addrs.EphemeralResourceMode:
return ret, fmt.Errorf("ephemeral resource %q detected in the plan. This is an error in OpenTofu", r.Addr.String())
default:
return nil, fmt.Errorf("resource %s has an unsupported mode %s",
r.Addr.String(),
r.Addr.Resource.Resource.Mode.String(),
)
}
schema, schemaVer := schemas.ResourceTypeConfig(
r.ProviderAddr.Provider,
r.Addr.Resource.Resource.Mode,
resource.Type,
)
if schema == nil {
return nil, fmt.Errorf("no schema found for %s", r.Addr.String())
}
resource.SchemaVersion = schemaVer
changeV, err := r.Decode(schema)
if err != nil {View on GitHub (pinned to 3561785c48)
Solutions
- If you are on a development or unreleased build, switch to the latest stable OpenTofu release.
- If you embed the engine, filter ephemeral-mode changes out of plans.Changes before calling jsonplan.Marshal.
- If it reproduces on a stable release, report it to the OpenTofu maintainers with the config and plan — the message explicitly asks for it.
Example fix
// before (embedding code): marshaling changes that may include ephemeral resources planJSON, err := jsonplan.Marshal(plan, schemas) // after: strip ephemeral-mode changes before marshaling filtered := filterEphemeral(plan.Changes) planJSON, err := jsonplan.Marshal(planWithChanges(filtered), schemas)
Defensive patterns
Strategy: validation
Validate before calling
// drop ephemeral-mode changes before handing plans.Changes to jsonplan (embedding code)
func withoutEphemeral(changes []*plans.ResourceInstanceChangeSrc) []*plans.ResourceInstanceChangeSrc {
out := changes[:0]
for _, c := range changes {
if c.Addr.Resource.Resource.Mode != addrs.EphemeralResourceMode {
out = append(out, c)
}
}
return out
} Type guard
func isEphemeralChange(c *plans.ResourceInstanceChangeSrc) bool {
return c.Addr.Resource.Resource.Mode == addrs.EphemeralResourceMode
} Prevention
- Use stable OpenTofu releases in production pipelines.
- Never assemble plans.Changes containing ephemeral resources programmatically.
When it happens
Trigger: Calling jsonplan.Marshal (directly or via `tofu show -json` / `tofu show -json plan.tfplan`) on a plans.Changes that contains a ResourceInstanceChangeSrc for an ephemeral resource address (addrs.EphemeralResourceMode). Upstream plan walking normally excludes ephemeral resources, so this requires a defect in plan construction or a programmatically assembled changes set.
Common situations: Ordinary CLI users do not hit this. It can appear when running a dev/nightly OpenTofu build with a regression in ephemeral-resource handling, or when code that embeds OpenTofu puts ephemeral resources into plans.Changes manually.
Related errors
- Failed to marshal get attr step name %#v: %w
- error in marshalPlanVariables: %w
- error in marshalPlannedValues: %w
- error in marshaling resource drift: %w
- error marshaling relevant attributes for external changes: %
AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15).
Data as JSON: /api/errors/ff5955060026dd8e.
Report an issue: GitHub.