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

  1. Inspect the wrapped error to identify the failing component
  2. Register the element type with beam.RegisterType before beam.Init
  3. Use a supported element type for the nullable coder
  4. 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

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)