{"record":{"id":"7b070aef3da9cf98","repo":"hashicorp/terraform","slug":"resource-s-has-an-unsupported-mode-s-7b070a","errorCode":null,"errorMessage":"resource %s has an unsupported mode %s","messagePattern":"resource (.+?) has an unsupported mode (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/command/jsonplan/plan.go","lineNumber":611,"sourceCode":"\tif key != nil {\n\t\tif key == addrs.WildcardKey {\n\t\t\t// The wildcard key should only be set for a deferred instance.\n\t\t\tr.IndexUnknown = true\n\t\t} else {\n\t\t\tvalue := key.Value()\n\t\t\tif r.Index, err = ctyjson.Marshal(value, value.Type()); err != nil {\n\t\t\t\treturn r, err\n\t\t\t}\n\t\t}\n\t}\n\n\tswitch addr.Resource.Resource.Mode {\n\tcase addrs.ManagedResourceMode:\n\t\tr.Mode = jsonstate.ManagedResourceMode\n\tcase addrs.DataResourceMode:\n\t\tr.Mode = jsonstate.DataResourceMode\n\tdefault:\n\t\treturn r, fmt.Errorf(\"resource %s has an unsupported mode %s\", r.Address, addr.Resource.Resource.Mode.String())\n\t}\n\tr.ModuleAddress = addr.Module.String()\n\tr.Name = addr.Resource.Resource.Name\n\tr.Type = addr.Resource.Resource.Type\n\tr.ProviderName = rc.ProviderAddr.Provider.String()\n\n\tswitch rc.ActionReason {\n\tcase plans.ResourceInstanceChangeNoReason:\n\t\tr.ActionReason = \"\" // will be omitted in output\n\tcase plans.ResourceInstanceReplaceBecauseCannotUpdate:\n\t\tr.ActionReason = ResourceInstanceReplaceBecauseCannotUpdate\n\tcase plans.ResourceInstanceReplaceBecauseTainted:\n\t\tr.ActionReason = ResourceInstanceReplaceBecauseTainted\n\tcase plans.ResourceInstanceReplaceByRequest:\n\t\tr.ActionReason = ResourceInstanceReplaceByRequest\n\tcase plans.ResourceInstanceReplaceByTriggers:\n\t\tr.ActionReason = ResourceInstanceReplaceByTriggers\n\tcase plans.ResourceInstanceDeleteBecauseNoResourceConfig:","sourceCodeStart":593,"sourceCodeEnd":629,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/command/jsonplan/plan.go#L593-L629","documentation":"Thrown by jsonplan.marshalResource while building the JSON plan: the switch over addr.Resource.Resource.Mode only maps addrs.ManagedResourceMode ('M') and addrs.DataResourceMode ('D'). ResourceMode also defines EphemeralResourceMode ('E'), ListResourceMode ('L'), and InvalidResourceMode (0), none of which have a JSON representation, so any of them lands in the default branch. The persistent JSON plan format is only defined for managed and data resources.","triggerScenarios":"An ephemeral or list resource (or one with a zero/Invalid mode) reaches the plan-change marshaling path; a new ResourceMode constant is added to internal/addrs without a case here; a corrupted in-memory plan object has Mode==0.","commonSituations":"Running an internal/dev Terraform build where ephemeral/list resources are being plumbed through plan serialization before the JSON layer is updated; a Terraform regression that routes an unsupported mode into MarshalResourceChanges; replaying a plan file produced by a mismatched Terraform binary.","solutions":["Upgrade Terraform to a release where the JSON plan serializer supports the resource mode you are using.","If you are extending Terraform, add a case for the new mode (or filter it out upstream) in internal/command/jsonplan/plan.go before calling marshalResource.","Report a bug at https://github.com/hashicorp/terraform/issues including the resource address and the mode string printed in the message.","Regenerate the plan with the same Terraform binary that will display it to avoid cross-version plan files."],"exampleFix":"// before\nswitch addr.Resource.Resource.Mode {\ncase addrs.ManagedResourceMode:\n\tr.Mode = jsonstate.ManagedResourceMode\ncase addrs.DataResourceMode:\n\tr.Mode = jsonstate.DataResourceMode\ndefault:\n\treturn r, fmt.Errorf(\"resource %s has an unsupported mode %s\", r.Address, addr.Resource.Resource.Mode.String())\n}\n\n// after (extend the serializer for the new mode or skip it)\ncase addrs.EphemeralResourceMode:\n\treturn r, fmt.Errorf(\"ephemeral resources are not represented in the JSON plan: %s\", r.Address)","handlingStrategy":"validation","validationCode":"// Before calling jsonplan marshalers, filter to the modes the JSON plan can represent.\nfunc jsonSerializableMode(m addrs.ResourceMode) bool {\n    switch m {\n    case addrs.ManagedResourceMode, addrs.DataResourceMode:\n        return true\n    }\n    return false\n}\n\nfor _, rc := range changes {\n    if !jsonSerializableMode(rc.Addr.Resource.Resource.Mode) {\n        continue // ephemeral/list/invalid are not part of the JSON plan\n    }\n    // ... marshal rc\n}","typeGuard":"func isJSONPlanSerializableResource(a addrs.ConfigResource) bool {\n    switch a.Resource.Mode {\n    case addrs.ManagedResourceMode, addrs.DataResourceMode:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Never pass ephemeral or list resources into the persistent JSON plan/state marshalers; they are intentionally unsupported.","Keep the Terraform binary that produces a plan identical to the one that displays it.","When extending Terraform with a new ResourceMode, update every mode switch in jsonplan and jsonstate in the same change."],"tags":["terraform","json-plan","resource-mode","serialization","enum-exhaustiveness"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}