apache/beam · error
failed to marshal Nullable coder
Error message
failed to marshal Nullable coder %v
What it means
Wrap returned by the coder marshaling path in Add when interning the component(s) of a coder.Nullable fails. The inner AddMulti error is wrapped with the coder being serialized; the real cause is in the wrapped error and usually means an inner (component) coder failed to marshal to its pipeline-proto representation.
Solutions
- Inspect the wrapped error to identify the failing component
- Register the element type with beam.RegisterType before beam.Init
- Use a supported element type for the nullable coder
- Upgrade the Beam Go SDK if support is missing
Defensive patterns
Strategy: try-catch
Try / catch
// Unwrap and log the inner component failure
if err != nil && strings.Contains(err.Error(), "Nullable") {
log.Printf("nullable component failure: %v", errors.Unwrap(err))
} Prevention
- Register nullable element types before beam.Init
- Keep nullable element types to supported kinds
- Catch the error during pipeline build, before submission
When it happens
Trigger: CoderBuilder.Add on a coder.Nullable whose element component coder fails to marshal.
Common situations: Nullable PCollections over custom types that were not registered; nested coders where the inner error names the real culprit.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/064a734f4921a661.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/runtime/graphx/coder.go:486
inner := b.internCoder(&pipepb.Coder{
Spec: &pipepb.FunctionSpec{
Urn: urnCustomCoder,
Payload: []byte(data),
},
})
return b.internBuiltInCoder(urnLengthPrefixCoder, inner), nil
case coder.KV:
comp, err := b.AddMulti(c.Components)
if err != nil {
return "", errors.Wrapf(err, "failed to marshal KV coder %v", c)
}
return b.internBuiltInCoder(urnKVCoder, comp...), nil
case coder.Nullable:
comp, err := b.AddMulti(c.Components)
if err != nil {
return "", errors.Wrapf(err, "failed to marshal Nullable coder %v", c)
}
return b.internBuiltInCoder(urnNullableCoder, comp...), nil
case coder.CoGBK:
comp, err := b.AddMulti(c.Components)
if err != nil {
return "", errors.Wrapf(err, "failed to marshal CoGBK coder %v", c)
}
value := comp[1]
if len(comp) > 2 {
// TODO(https://github.com/apache/beam/issues/18032): don't inject union coder for CoGBK.
union := b.internBuiltInCoder(urnCoGBKList, comp[1:]...)
value = b.internBuiltInCoder(urnLengthPrefixCoder, union)
}
// SDKs always provide iterableCoder to runners, but can receive StateBackedIterables in return.
stream := b.internBuiltInCoder(urnIterableCoder, value)View on GitHub (pinned to 12126d8942)