ErrLookupBackground articles › json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it

json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it

"json marshal failed", "failed to marshal request body", or "unsupported type" errors from Go's encoding/json mean a value could not be serialized to JSON — typically because the data contains a channel, func, cyclic reference, NaN/Inf float, or a custom MarshalJSON that returned an error. This family gathers that failure mode across Go libraries and shows how to find the offending field and fix it.

Distilled from 108 documented records across 22 repositories.

Background

Every record in this family comes from the same place: a call to json.Marshal, json.MarshalIndent, or json.NewEncoder(...).Encode in a Go library, wrapped and re-raised with library-specific context like "failed to marshal GraphQL request: %w", "encoding value: %w", or "marshaling request object as JSON: %w". The error exists because encoding/json is a total serializer only for JSON-shaped data: strings, numbers, booleans, nil, slices, maps with string-like keys, and structs of those. Values outside that set — channels, funcs, complex numbers, unsafe pointers, NaN and ±Inf floats, and cyclic or self-referential structures — make the marshal call fail at runtime rather than at compile time, and the library has to decide what to do with that failure.

From the caller's side the error is almost always unexpected, and the records show why: in the overwhelming majority of cases the thing being marshaled is a plain struct or map of strings and numbers, and the library authors themselves flag the branch as "practically unreachable" or "defensive." Tailscale's operator marshals a Records struct of strings and string slices and calls the error effectively unreachable; charmbracelet/crush wraps a marshal of a struct with two string fields; beads wraps json.Marshal on a single Go string and notes it "cannot fail in current Go." When such an error does fire, it signals one of a small set of conditions: a non-serializable value was injected somewhere upstream, a custom MarshalJSON method returned an error, a float became NaN/Inf (for example via division by zero), or the binary was built from modified code or mismatched versions.

The family varies mainly in how much context the wrapper gives you and what it means operationally. Some wrappers name the offending object — cilium prints the patch it could not serialize ("json.Marshal(%v) failed"), logtail identifies the buffered entry by sequence number ("logtail: encoding entry %d"), and beads names the issue ID ("failed to marshal issue %s"). Others are generic. The consequence also varies: in pulumi's REST client the HTTP request is never sent; in navidrome's inspect endpoint and vitess's /twopcz handler the raw error text is written as an HTTP 500 body (which itself leaks implementation detail); in tailscale's logtail the entire log upload batch is aborted. In most other cases persistence, export, or a debug endpoint simply fails.

Because the underlying cause lives in the data rather than the call site, the reliable diagnosis path is the same everywhere: unwrap the %w error to see the concrete json.UnsupportedTypeError (unsupported type) or json.UnsupportedValueError (unsupported value such as NaN or a cycle), then inspect the named object for fields holding channels, funcs, cyclic references, non-finite floats, or a custom Marshaler with an error path. Several libraries add extra wrinkle: siyuan and gofr marshal through helper wrappers (gulu.JSON.MarshalIndentJSON, a bulk encoder) that preserve the same semantics, and waveterm's tool-input parsing deliberately round-trips loosely-typed input through marshal/unmarshal, so caller-supplied data — not library-internal state — is the usual culprit there.

Common causes

What usually fixes it

Go deeper

Documented occurrences

…and 88 more across the corpus — use search.

Honest provenance: generated on 2026-09-01 from AI-assisted analysis of the linked records. See how records are made.