apache/beam · error
failed to marshal receiver %v
Error message
failed to marshal receiver %v
What it means
encodeFn marshals the DoFn receiver value to JSON (via jsonx.Marshal) to embed in the Fn proto's Opt field; this error means that JSON marshaling of the user's DoFn struct failed. Usually the struct contains fields JSON cannot represent (channels, funcs, unexported-only state, cycles).
Source
Thrown at sdks/go/pkg/beam/core/runtime/graphx/serialize.go:259
t := reflect.TypeOf(u.Recv)
k, ok := runtime.TypeKey(reflectx.SkipPtr(t))
if !ok {
err := errors.Errorf("failed to create TypeKey for receiver type %T", u.Recv)
return nil, errors.WithContextf(err, "encoding structural DoFn %v", u)
}
if _, ok := runtime.LookupType(k); !ok {
err := errors.Errorf("receiver type %v must be registered", t)
return nil, errors.WithContextf(err, "encoding structural DoFn %v", u)
}
typ, err := encodeType(t)
if err != nil {
wrapped := errors.Wrapf(err, "failed to encode receiver type %T", u.Recv)
return nil, errors.WithContextf(wrapped, "encoding structural DoFn %v", u)
}
data, err := jsonx.Marshal(u.Recv)
if err != nil {
wrapped := errors.Wrapf(err, "failed to marshal receiver %v", u.Recv)
return nil, errors.WithContextf(wrapped, "encoding structural DoFn %v", u)
}
return &v1pb.Fn{Type: typ, Opt: string(data)}, nil
default:
return nil, errors.Errorf("failed to encode DoFn %v, missing fn", u)
}
}
func decodeFn(u *v1pb.Fn) (*graph.Fn, error) {
if u.Dynfn != nil {
gen, err := runtime.ResolveFunction(u.Dynfn.Gen, genFnType)
if err != nil {
wrapped := errors.Wrapf(err, "bad symbol %v", u.Dynfn.Gen)
return nil, errors.WithContextf(wrapped, "decoding dynamic DoFn %v", u)
}
t, err := decodeType(u.Dynfn.Type)View on GitHub (pinned to 12126d8942)
Solutions
- Remove func/chan/unserializable fields from the DoFn struct, or mark them `json:"-"` if they can be reconstructed.
- Move non-serializable state out of the DoFn and pass it via side inputs or closure-free configuration.
- Fix any custom MarshalJSON implementations on receiver fields.
- Keep DoFn receiver as a plain data struct with JSON-safe exported fields.
Example fix
// before
type myFn struct{ cb func(int) }
// after
type myFn struct {
cb func(int) `json:"-"` // reinitialized in Setup()
} Defensive patterns
Strategy: validation
Validate before calling
if _, err := json.Marshal(fn.Recv); err != nil {
return fmt.Errorf("DoFn receiver not JSON-serializable: %w", err)
} Type guard
func jsonSafe(v interface{}) bool { _, err := json.Marshal(v); return err == nil } Try / catch
_, err := json.Marshal(recv)
if err != nil {
return fmt.Errorf("DoFn %T not serializable: %w", recv, err)
} Prevention
- Keep DoFn receiver structs free of func/chan fields or tag them `json:"-"`.
- Unit-test json.Marshal on every custom DoFn value.
- Initialize transient fields in Setup(), not in the struct literal.
When it happens
Trigger: EncodeMultiEdge on a structural DoFn whose receiver contains a func, chan, complex number, cyclic reference, or a MarshalJSON implementation that errors.
Common situations: DoFn structs holding callback functions or channels for convenience; custom types with broken MarshalJSON methods; side-input state stored as unserializable fields.
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
- empty type
- invalid float encoding for: %v
- could not unmarshal stream type coder from %v, stream must b
- could not unmarshal CoderRef from %v, failed to decode urn-l
- could not unmarshal CoderRef from %v, failed to decode Coder
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/abdf5aff56a5b4fd.
Report an issue: GitHub.