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

  1. Inspect the wrapped cause from encodeType to see which component type is unrepresentable.
  2. Replace anonymous/unnamed types with named, registered types.
  3. Use a standard named struct DoFn instead of dynamically constructed types.
  4. 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

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)