hashicorp/terraform · error
: cannot serialize value marked as %#v for inclusion in a…
Error message
%s: cannot serialize value marked as %#v for inclusion in a state snapshot (this is a bug in Terraform)
What it means
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.
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.
Example fix
// before
_, otherMarks = marks.PathsWithMark(otherMarks, marks.Deprecation)
if len(otherMarks) != 0 {
return 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)
}
// after (teach the serializer about the new mark, e.g. marks.Example)
_, otherMarks = marks.PathsWithMark(otherMarks, marks.Example)
if len(otherMarks) != 0 {
return cty.NilVal, nil, fmt.Errorf("...")
} Defensive patterns
Strategy: try-catch
Validate before calling
// If you build values destined for state, strip all but persistable marks first.
func safeForState(v cty.Value) (cty.Value, error) {
v, paths := v.UnmarkDeepWithPaths()
_, other := marks.PathsWithMark(paths, marks.Sensitive)
_, other = marks.PathsWithMark(other, marks.Deprecation)
if len(other) != 0 {
return cty.NilVal, fmt.Errorf("value carries non-persistable mark %v at %s", other[0].Marks, tfdiags.FormatCtyPath(other[0].Path))
}
return v, nil
} Type guard
func hasOnlyPersistableMarks(v cty.Value) bool {
_, paths := v.UnmarkDeepWithPaths()
_, other := marks.PathsWithMark(paths, marks.Sensitive)
_, other = marks.PathsWithMark(other, marks.Deprecation)
return len(other) == 0
} Try / catch
if _, err := jsonstate.Marshal(state, schemas); err != nil && strings.Contains(err.Error(), "this is a bug in Terraform") {
// Not recoverable by config; report upstream with the mark from the message.
log.Printf("internal Terraform bug: %v", err)
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- preparing attribute values for
- preparing identity values for
- resource has an unsupported mode
- Error initializing backend %T
- error reading output values
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/d54241dbd0fd1837.
Report an issue: GitHub.
Appendix: source
Thrown at internal/command/jsonstate/state.go:624
panic(fmt.Sprintf("sensitiveAsBool cannot handle %#v", val))
}
}
// unmarkValueForMarshaling takes a value that possibly contains marked values
// and returns an equal value without markings along with the separated mark
// metadata that should be presented alongside the value in another JSON
// property.
//
// This function only accepts the marks that are valid to persist, and so will
// return an error if other marks are present. Marks that this package doesn't
// know how to store must be dealt with somehow by a caller -- presumably by
// replacing each marked value with some sort of storage placeholder.
func unmarkValueForMarshaling(v cty.Value) (unmarkedV cty.Value, sensitivePaths []cty.Path, err error) {
val, pvms := v.UnmarkDeepWithPaths()
sensitivePaths, otherMarks := marks.PathsWithMark(pvms, marks.Sensitive)
_, otherMarks = marks.PathsWithMark(otherMarks, marks.Deprecation)
if len(otherMarks) != 0 {
return 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,
)
}
return val, sensitivePaths, err
}
View on GitHub (pinned to d32a084675)