apache/beam · error
failed to encode receiver type %T
Error message
failed to encode receiver type %T
What it means
encodeFn fails to serialize the DoFn receiver's type via encodeType after the registration check passed. This means the type is registered but its type descriptor cannot be encoded into the pipeline proto, typically because it contains a component type graphx cannot represent.
Solutions
- Inspect the wrapped cause from encodeType to see which component type is unrepresentable.
- Replace anonymous/unnamed types with named, registered types.
- Use a standard named struct DoFn instead of dynamically constructed types.
- Update to a newer Beam version if the type is a normal named type (codec coverage has expanded over releases).
Example fix
// before
typ := reflect.StructOf([]reflect.StructField{{Name: "X", Type: reflect.TypeOf(0)}})
fn := reflect.New(typ).Interface().(beam.DoFn)
// after
type myFn struct{ X int }
var fn beam.DoFn = &myFn{} Defensive patterns
Strategy: validation
Validate before calling
if _, err := encodeType(reflect.TypeOf(myFn{})); err != nil {
return fmt.Errorf("receiver type not encodable: %w", err)
} Type guard
func isNamedRegistered(t reflect.Type) bool {
return t.Name() != "" && t.PkgPath() != ""
} Prevention
- Use named, top-level struct types for DoFns; avoid reflect.StructOf and anonymous types.
- Test pipeline encoding locally with graphx.EncodeMultiEdge before submitting.
When it happens
Trigger: EncodeMultiEdge on a structural DoFn whose receiver type (or one of its type parameters) resolves to an unsupported/anonymous/unrepresentable type passed to encodeType.
Common situations: DoFns built with generics or reflection-created types that have no stable name; types with unnamed struct or interface components that the graphx type codec can't map to a named type.
Related errors
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/793f17bf8e9b30e9.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/runtime/graphx/serialize.go:253
wrapped := errors.Wrap(err, "bad userfn")
return nil, errors.WithContextf(wrapped, "encoding DoFn %v", u)
}
return &v1pb.Fn{Fn: fn}, nil
case u.Recv != nil:
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)View on GitHub (pinned to 12126d8942)