apache/beam · error

failed to find %v method

Error message

failed to find %v method

What it means

AsDoFn requires the Fn's methods map to contain a ProcessElement method. When absent it reports "failed to find ProcessElement method". For non-pointer receivers this usually means reflection cannot see the method because the struct was passed by value.

Source

Thrown at sdks/go/pkg/beam/core/graph/fn.go:503

// AsDoFn converts a Fn to a DoFn, if possible. numMainIn specifies how many
// main inputs are expected in the DoFn's method signatures. Valid inputs are
// the package constants of type mainInputs. If that number is MainUnknown then
// validation is done by best effort and may miss some edge cases.
func AsDoFn(fn *Fn, numMainIn mainInputs) (*DoFn, error) {
	addContext := func(err error, fn *Fn) error {
		return errors.WithContextf(err, "graph.AsDoFn: for Fn named %v", fn.Name())
	}

	if fn.methods == nil {
		fn.methods = make(map[string]*funcx.Fn)
	}
	if fn.Fn != nil {
		fn.methods[processElementName] = fn.Fn
	}

	if _, ok := fn.methods[processElementName]; !ok {
		err := errors.Errorf("failed to find %v method", processElementName)
		if fn.Recv != nil {
			v := reflect.ValueOf(fn.Recv)
			if v.Kind() != reflect.Ptr {
				err = errors.Wrap(err, "structural DoFn passed by value, ensure that the ProcessElement method has a value receiver or pass the DoFn by pointer")
			}
		}
		return nil, addContext(err, fn)
	}

	// Make sure that all state entries have keys. If they don't set them to the struct field name.
	if fn.Recv != nil {
		v := reflect.Indirect(reflect.ValueOf(fn.Recv))
		for i := 0; i < v.NumField(); i++ {
			f := v.Field(i)
			if f.CanInterface() {
				if ps, ok := f.Interface().(state.PipelineState); ok {
					if ps.StateKey() == "" {
						f.FieldByName("Key").SetString(v.Type().Field(i).Name)

View on GitHub (pinned to 12126d8942)

Solutions

  1. Ensure the DoFn defines a ProcessElement method
  2. Pass the DoFn by pointer: beam.ParDo(s, &myFn{}, in)
  3. Or change ProcessElement to a value receiver

Example fix

// before
beam.ParDo(s, myFn{}, in) // ProcessElement has pointer receiver
// after
beam.ParDo(s, &myFn{}, in)
Defensive patterns

Strategy: validation

Validate before calling

if reflect.ValueOf(fn).Kind() == reflect.Struct { _, ok := reflect.TypeOf(fn).MethodByName("ProcessElement"); if !ok { return errors.New("no ProcessElement method in value's method set") } }

Type guard

func hasProcessElement(fn any) bool {
  t := reflect.TypeOf(fn)
  if t == nil { return false }
  _, ok := t.MethodByName("ProcessElement")
  return ok
}

Try / catch

dfn, err := graph.NewDoFn(fn)
if err != nil && strings.Contains(err.Error(), "failed to find ProcessElement") {
    return fmt.Errorf("%T lacks reachable ProcessElement; pass by pointer or add the method", fn)
}

Prevention

When it happens

Trigger: Calling NewDoFn/AsDoFn on a structural DoFn (no ProcessElement method defined) or on a struct passed by value whose ProcessElement has a pointer receiver.

Common situations: Defining ProcessElement with a pointer receiver but passing the struct by value into beam.ParDo; forgetting ProcessElement entirely on a struct-based DoFn.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/a1562602b32e510a. Report an issue: GitHub.