apache/beam · error

method has no main inputs

Error message

%v method has no main inputs

What it means

Error returned by validateMainInputs when method.Inputs() reports zero usable inputs for the method being validated (with numMainIn unknown defaulting to MainSingle). It means the DoFn method (e.g. ProcessElement or @OnTimer) declares no main input parameters at all, so the signature cannot satisfy even the minimum single-main-input requirement.

Solutions

  1. Add a main input parameter to ProcessElement matching the PCollection element type
  2. If source-like behavior is intended, use a beam.Impulse + root transform instead of a DoFn without input
  3. Check the InputType/numMainIn configuration when using multi-input DoFns

Example fix

// before
func (f *MyFn) ProcessElement(emit func(int)) { ... }
// after
func (f *MyFn) ProcessElement(ctx context.Context, s string, emit func(int)) { ... }
Defensive patterns

Strategy: validation

Validate before calling

m, _ := reflect.TypeOf(fn).MethodByName("ProcessElement")
if m != (reflect.Method{}) && m.Type.NumIn() < 3 { // recv + (ctx) + main input
  return errors.New("ProcessElement must declare a main input parameter")
}

Prevention

When it happens

Trigger: Defining ProcessElement with only a context and/or emit functions but no main input parameter, e.g. ProcessElement(ctx context.Context, emit func(string)).

Common situations: Writing a generator-style DoFn expecting to emit without consuming input; accidental deletion of the element parameter during refactoring.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

	err = validateTimer(doFn, numMainIn)
	if err != nil {
		return nil, addContext(err, fn)
	}

	return doFn, nil
}

// validateMainInputs checks that a method has the given number of main inputs
// and that main inputs are before any side inputs.
func validateMainInputs(fn *Fn, method *funcx.Fn, methodName string, numMainIn mainInputs) error {
	if numMainIn == MainUnknown {
		numMainIn = MainSingle // If unknown, validate for minimum number of inputs.
	}

	// Make sure there are enough inputs (at least numMainIn)
	pos, num, ok := method.Inputs()
	if !ok {
		err := errors.Errorf("%v method has no main inputs", methodName)
		err = errors.SetTopLevelMsgf(err,
			"Method %v in DoFn %v is missing all inputs. A main input is required.",
			methodName, fn.Name())
		return err
	}
	if num < int(numMainIn) {
		err := errors.Errorf("%v method has too few main inputs", methodName)
		err = errors.SetTopLevelMsgf(err,
			"Method %v in DoFn %v does not have enough main inputs. "+
				"%v main inputs were expected, but only %v inputs were found.",
			methodName, fn.Name(), numMainIn, num)
		return err
	}

	// Check that the first input is not an Iter or ReIter (those aren't valid
	// as the first main input).
	first := method.Param[pos].Kind
	if first != funcx.FnValue {

View on GitHub (pinned to 12126d8942)