{"record":{"id":"d54241dbd0fd1837","repo":"hashicorp/terraform","slug":"s-cannot-serialize-value-marked-as-v-for-inclu","errorCode":null,"errorMessage":"%s: cannot serialize value marked as %#v for inclusion in a state snapshot (this is a bug in Terraform)","messagePattern":"(.+?): cannot serialize value marked as %#v for inclusion in a state snapshot \\(this is a bug in Terraform\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/command/jsonstate/state.go","lineNumber":624,"sourceCode":"\t\tpanic(fmt.Sprintf(\"sensitiveAsBool cannot handle %#v\", val))\n\t}\n}\n\n// unmarkValueForMarshaling takes a value that possibly contains marked values\n// and returns an equal value without markings along with the separated mark\n// metadata that should be presented alongside the value in another JSON\n// property.\n//\n// This function only accepts the marks that are valid to persist, and so will\n// return an error if other marks are present. Marks that this package doesn't\n// know how to store must be dealt with somehow by a caller -- presumably by\n// replacing each marked value with some sort of storage placeholder.\nfunc unmarkValueForMarshaling(v cty.Value) (unmarkedV cty.Value, sensitivePaths []cty.Path, err error) {\n\tval, pvms := v.UnmarkDeepWithPaths()\n\tsensitivePaths, otherMarks := marks.PathsWithMark(pvms, marks.Sensitive)\n\t_, otherMarks = marks.PathsWithMark(otherMarks, marks.Deprecation)\n\tif len(otherMarks) != 0 {\n\t\treturn cty.NilVal, nil, fmt.Errorf(\n\t\t\t\"%s: cannot serialize value marked as %#v for inclusion in a state snapshot (this is a bug in Terraform)\",\n\t\t\ttfdiags.FormatCtyPath(otherMarks[0].Path), otherMarks[0].Marks,\n\t\t)\n\t}\n\treturn val, sensitivePaths, err\n}\n","sourceCodeStart":606,"sourceCodeEnd":631,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/command/jsonstate/state.go#L606-L631","documentation":"Thrown by jsonstate.unmarkValueForMarshaling. It strips cty marks via UnmarkDeepWithPaths, then separates out the Sensitive and Deprecation marks (the only two the state format can persist). If any other mark remains, serialization aborts because the state format has no way to store it. The message explicitly states this is a bug in Terraform: some upstream code path left a mark on a value bound for the state snapshot.","triggerScenarios":"A cty mark type other than Sensitive/Deprecation (e.g. an experimental or custom mark) is applied to a value that reaches state serialization; a new feature added a mark without teaching unmarkValueForMarshaling how to handle it; an internal regression left ephemeral marks on persisted values.","commonSituations":"Pre-release/experimental Terraform features that introduce new marks; provider/SDK applying non-standard marks; memory/object aliasing causing a mark to leak onto a persisted value.","solutions":["Upgrade Terraform to a release that handles the mark type shown in the message.","Report a bug at https://github.com/hashicorp/terraform/issues with the mark value (%#v) and the path from the message.","Reproduce with `terraform plan`/`apply` and identify which resource/attribute carries the mark, then simplify that configuration to avoid the triggering feature.","If extending Terraform, strip or persist the new mark in unmarkValueForMarshaling before serialization."],"exampleFix":"// before\n_, otherMarks = marks.PathsWithMark(otherMarks, marks.Deprecation)\nif len(otherMarks) != 0 {\n\treturn cty.NilVal, nil, fmt.Errorf(\"%s: cannot serialize value marked as %#v for inclusion in a state snapshot (this is a bug in Terraform)\", tfdiags.FormatCtyPath(otherMarks[0].Path), otherMarks[0].Marks)\n}\n\n// after (teach the serializer about the new mark, e.g. marks.Example)\n_, otherMarks = marks.PathsWithMark(otherMarks, marks.Example)\nif len(otherMarks) != 0 {\n\treturn cty.NilVal, nil, fmt.Errorf(\"...\")\n}","handlingStrategy":"try-catch","validationCode":"// If you build values destined for state, strip all but persistable marks first.\nfunc safeForState(v cty.Value) (cty.Value, error) {\n    v, paths := v.UnmarkDeepWithPaths()\n    _, other := marks.PathsWithMark(paths, marks.Sensitive)\n    _, other = marks.PathsWithMark(other, marks.Deprecation)\n    if len(other) != 0 {\n        return cty.NilVal, fmt.Errorf(\"value carries non-persistable mark %v at %s\", other[0].Marks, tfdiags.FormatCtyPath(other[0].Path))\n    }\n    return v, nil\n}","typeGuard":"func hasOnlyPersistableMarks(v cty.Value) bool {\n    _, paths := v.UnmarkDeepWithPaths()\n    _, other := marks.PathsWithMark(paths, marks.Sensitive)\n    _, other = marks.PathsWithMark(other, marks.Deprecation)\n    return len(other) == 0\n}","tryCatchPattern":"if _, err := jsonstate.Marshal(state, schemas); err != nil && strings.Contains(err.Error(), \"this is a bug in Terraform\") {\n    // Not recoverable by config; report upstream with the mark from the message.\n    log.Printf(\"internal Terraform bug: %v\", err)\n    return err\n}","preventionTips":["Keep Terraform current; new mark types are added to unmarkValueForMarshaling in the same release that introduces them.","If you maintain a provider/SDK, never apply custom cty marks to values that will reach state.","When hitting this, capture the exact mark (%#v) and path from the message for the upstream report."],"tags":["terraform","json-state","cty-marks","bug","serialization"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}