hashicorp/terraform · critical
json.MarshalIndent error (dynamic)
Error message
json.MarshalIndent error (dynamic)
What it means
Terraform panics in ShowJSON.DisplayResourceInstanceState when json.MarshalIndent fails on the 'terraform state show -json <addr>' output struct (FormatVersion + a jsonstate.Resource + diagnostics). The code comment asserts this 'should never happen because we fully-control the input', so a panic here means the resource state being serialized contains a value encoding/json cannot represent.
Source
Thrown at internal/command/views/show.go:231
output.Diagnostics = []*viewsjson.Diagnostic{}
}
var rs jsonstate.Resource
if !jsonState.Empty() {
// we know there's only one resource instance, but we need to find it.
if len(jsonState.RootModule.Resources) > 0 {
rs = jsonState.RootModule.Resources[0]
} else {
rs = findResourceInChildModules(jsonState.RootModule)
}
}
output.Resource = rs
j, err := json.MarshalIndent(&output, "", " ")
if err != nil {
// Should never happen because we fully-control the input here
panic(err)
}
v.view.streams.Println(string(j))
if diags.HasErrors() {
return 1
}
return 0
}
func findResourceInChildModules(mod jsonstate.Module) jsonstate.Resource {
for _, cm := range mod.ChildModules {
if len(cm.Resources) == 1 {
return cm.Resources[0]
}
}
for _, child := range mod.ChildModules {
return findResourceInChildModules(child)
}View on GitHub (pinned to d32a084675)
Solutions
- Inspect the exact resource address and provider involved; reproduce with 'terraform state show -json <addr>' and capture the stack trace, then check the resource attributes for NaN/Inf or non-serializable values.
- If the state is corrupted, use 'terraform state pull' / edit the JSON / 'terraform state push' to remove the offending attribute, or restore a known-good state backup from the workspace .terraform/ or remote backend history.
- Report the bug to Terraform with the goroutine trace and the provider/schema that produced the unmarshallable value; the defensive panic indicates a serialization contract was violated upstream.
- Pin to a known-good provider/binary version that does not emit the offending value while the upstream fix lands.
Example fix
// before
j, err := json.MarshalIndent(&output, "", " ")
if err != nil {
// Should never happen because we fully-control the input here
panic(err)
}
// after (fail gracefully instead of crashing the CLI)
j, err := json.MarshalIndent(&output, "", " ")
if err != nil {
v.view.streams.Eprintf("Failed to marshal resource state to json: %s", err)
return 1
} Defensive patterns
Strategy: validation
Validate before calling
// Before calling DisplayResourceInstanceState, sanity-check the resource you
// are about to render does not contain non-serializable numeric values.
func isMarshallableResource(rs jsonstate.Resource) error {
// jsonstate.Resource marshals via encoding/json; the only realistic
// failure modes are NaN/Inf in numeric attributes or a custom
// MarshalJSON error. Walk the attribute JSON if you have it.
raw, err := json.Marshal(rs)
if err != nil {
return fmt.Errorf("resource would fail json marshal: %w", err)
}
_ = raw
return nil
} Try / catch
// Wrap CLI entry points so an unexpected MarshalIndent panic degrades to a
// non-zero exit + message instead of an uncaught goroutine crash.
func runShowJSON(ctx context.Context, fn func() int) (code int) {
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "terraform: aborted show -json: %v\n", r)
code = 1
}
}()
return fn()
} Prevention
- Treat any hit of this panic as a bug: capture the stack trace and the resource address, and check the state for NaN/Inf or provider-schema oddities.
- Keep state backups so a corrupted/unmarshallable resource can be restored without the CLI crash blocking recovery.
- Pin provider versions that produce known-good, JSON-serializable attribute values.
When it happens
Trigger: Calling view.DisplayResourceInstanceState in ShowJSON (internal/command/views/show.go:228) where the assembled Output struct holds a jsonstate.Resource whose MarshalJSON or nested cty/JSON value returns an error. json.MarshalIndent returns a non-nil error for unsupported values: chan/func/math.NaN/math.Inf/cyclic refs, or a custom MarshalJSON that errors.
Common situations: A state file built from a provider whose schema produced a numeric value that became NaN/Inf, hand-edited or corrupted state, a third-party provider emitting a value Terraform's jsonstate marshaller cannot round-trip, or an internal regression in jsonstate.Resource marshaling after a schema change.
Related errors
- resource not found in state
- Failed to marshal state to json: %s
- FormatValueStr error (dynamic)
- ErrInvalidRemotePlanFormat
- ErrInvalidRunID
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/a17a49ebb6b79481.
Report an issue: GitHub.