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

  1. Upgrade Terraform to a release that handles the mark type shown in the message.
  2. Report a bug at https://github.com/hashicorp/terraform/issues with the mark value (%#v) and the path from the message.
  3. Reproduce with `terraform plan`/`apply` and identify which resource/attribute carries the mark, then simplify that configuration to avoid the triggering feature.
  4. 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

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


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)