apache/beam · error

method invalid

Error message

method %v invalid

What it means

When NewFn constructs an Fn from a struct or interface, it wraps the type's lifecycle methods via reflectx.WrapMethods and builds each into a funcx.New callable. If any method's signature cannot be converted into a valid beam function (e.g., wrong parameter or return types), the error from funcx.New is wrapped as "method %v invalid". This surfaces at fn-registration time, before any element is processed.

Solutions

  1. Read the wrapped inner error to see which signature rule the named method violates.
  2. Fix the method signature to match beam requirements (e.g., MergeAccumulators(acc A) A; ProcessElement with valid ctx/input/emit/iterator params).
  3. Compare against a working example DoFn/CombineFn in the beam Go SDK and mirror its parameter and return forms.
  4. After an SDK version change, re-check lifecycle method signatures against the new funcx validation rules.

Example fix

// before
func (fn *myFn) ProcessElement(x int, y string) {} // unbindable: extra plain param without matching input
// after
func (fn *myFn) ProcessElement(x int) string { return strconv.Itoa(x) }
Defensive patterns

Strategy: validation

Validate before calling

// Go: smoke-test the DoFn signature at startup before building pipelines
if _, err := graph.NewDoFn(&myDoFn{}); err != nil {
    log.Fatalf("invalid DoFn signature: %v", err)
}

Type guard

func validDoFn(fn interface{}) error {
    _, err := graph.NewDoFn(fn)
    return err
}

Try / catch

// Go: wrap NewFn/NewDoFn errors with method context
if _, err := graph.NewDoFn(myFn); err != nil {
    return fmt.Errorf("DoFn %T rejected (check lifecycle method signatures): %w", myFn, err)
}

Prevention

When it happens

Trigger: Defining a DoFn/CombineFn method (e.g., ProcessElement, CreateAccumulator, AddInput, MergeAccumulators, Setup, Teardown) with a signature funcx cannot bind — wrong argument kinds, unsupported return values, or missing required outputs.

Common situations: CombineFns where MergeAccumulators lacks the required accumulator return; ProcessElement with an unsupported iterator/emitter misuse; renaming/mis-signing lifecycle methods after an SDK upgrade; typos in method parameters like the emit function type.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

		// Note that a ptr receiver is necessary if struct fields are updated in the
		// user code. Otherwise, updates are simply lost.
		fallthrough

	case reflect.Struct:
		methods := make(map[string]*funcx.Fn)
		annotations := make(map[string][]byte)
		af := reflect.Indirect(val).FieldByName("Annotations")
		if af.IsValid() {
			a, ok := af.Interface().(map[string][]byte)
			if ok {
				annotations = a
			}
		}
		if methodsFuncs, ok := reflectx.WrapMethods(fn); ok {
			for name, mfn := range methodsFuncs {
				f, err := funcx.New(mfn)
				if err != nil {
					return nil, errors.Wrapf(err, "method %v invalid", name)
				}
				methods[name] = f
			}
		}
		for mName := range lifecycleMethods {
			if _, ok := methods[mName]; ok {
				continue // skip : already wrapped
			}
			m, ok := val.Type().MethodByName(mName)
			if !ok {
				continue // skip: doesn't exist
			}

			// CAVEAT(herohde) 5/22/2017: The type val.Type.Method.Type is not
			// the same as val.Method.Type: the former has the explicit receiver.
			// We'll use the receiver-less version.
			f, err := funcx.New(reflectx.MakeFunc(val.Method(m.Index).Interface()))
			if err != nil {

View on GitHub (pinned to 12126d8942)