apache/beam · error
bad return type
Error message
bad return type
What it means
encodeType serializes func types by encoding each return type; 'bad return type' means one of the function's output types failed to encode. Like the parameter-side error, it surfaces when exporting a DoFn or user function whose emit/output types cannot be represented on the wire.
Solutions
- Change the return/emitted type to an encodable form (slice of exported-field structs).
- Register the custom output type in the Beam type registry.
- Split emission into encodable sub-values (emit each map entry as a KV struct).
- Use the 'encoding function %v' context message to identify the failing signature.
Example fix
// before
func parse(line string) map[string]string { ... }
// after
type Field struct { K, V string }
func parse(line string) []Field { ... } Defensive patterns
Strategy: validation
Validate before calling
ft := reflect.TypeOf(fn)
for i := 0; i < ft.NumOut(); i++ {
if err := isEncodableType(ft.Out(i)); err != nil {
return fmt.Errorf("return %d of %v unencodable: %w", i, ft, err)
}
} Type guard
func encodableReturns(fn any) bool { t := reflect.TypeOf(fn); if t.Kind() != reflect.Func { return false }; for i := 0; i < t.NumOut(); i++ { if isEncodableType(t.Out(i)) != nil { return false } }; return true } Try / catch
if !encodableReturns(fn) {
return fmt.Errorf("function %T returns unserializable types", fn)
} Prevention
- Return slices/structs of exported fields, never maps or arrays
- Emit KV structs instead of map results from DoFns
- Test each DoFn's signature against encodeType in unit tests
When it happens
Trigger: A user function returns (or emits via a func outlet parameter) a type that encodeType cannot encode: map/array returns, structs with unexported fields, or unregistered custom types.
Common situations: DoFns emitting map results; builders returning structs with private fields; pipelines exported for Flink/Dataflow/Spark runners.
Related errors
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/aa2246789315877f.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/runtime/graphx/serialize.go:479
fields = append(fields, field)
}
return &v1pb.Type{Kind: v1pb.Type_STRUCT, Fields: fields}, nil
case reflect.Func:
var in []*v1pb.Type
for i := 0; i < t.NumIn(); i++ {
param, err := encodeType(t.In(i))
if err != nil {
wrapped := errors.Wrap(err, "bad parameter type")
return nil, errors.WithContextf(wrapped, "encoding function %v", t)
}
in = append(in, param)
}
var out []*v1pb.Type
for i := 0; i < t.NumOut(); i++ {
ret, err := encodeType(t.Out(i))
if err != nil {
wrapped := errors.Wrap(err, "bad return type")
return nil, errors.WithContextf(wrapped, "encoding function %v", t)
}
out = append(out, ret)
}
return &v1pb.Type{Kind: v1pb.Type_FUNC, ParameterTypes: in, ReturnTypes: out, IsVariadic: t.IsVariadic()}, nil
case reflect.Chan:
elm, err := encodeType(t.Elem())
if err != nil {
wrapped := errors.Wrap(err, "bad element type")
return nil, errors.WithContextf(wrapped, "encoding channel %v", t)
}
dir, err := encodeChanDir(t.ChanDir())
if err != nil {
wrapped := errors.Wrap(err, "bad channel direction")
return nil, errors.WithContextf(wrapped, "encoding channel %v", t)
}
return &v1pb.Type{Kind: v1pb.Type_CHAN, Element: elm, ChanDir: dir}, nilView on GitHub (pinned to 12126d8942)