apache/beam · error

: requires at least 1 return value.

Error message

%v: %v requires at least 1 return value. : %v

What it means

MergeAccumulators must return the accumulator type; its first return value defines the accumulator type A that all other CombineFn methods must match. If the method returns no values, fn.go cannot determine the accumulator type and rejects the CombineFn with this error.

Solutions

  1. Change MergeAccumulators to return at least one value of the accumulator type, e.g. `func (c *C) MergeAccumulators(a, b Acc) Acc`.
  2. Make sure all other methods (CreateAccumulator, AddInput, ExtractOutput) use that same accumulator type.
  3. Remove error return confusion — errors are optional extra returns, but the accumulator must be first.

Example fix

// before
func (c *Sum) MergeAccumulators(a, b int) { c.total = a + b }
// after
func (c *Sum) MergeAccumulators(a, b int) int { return a + b }
Defensive patterns

Strategy: validation

Validate before calling

// static check at init
var _ = func() {
    mt := reflect.TypeOf((*Sum)(nil)).MethodByName("MergeAccumulators")
    if mt.Type.NumOut() == 0 { panic("MergeAccumulators must return the accumulator") }
}

Prevention

When it happens

Trigger: Defining MergeAccumulators with zero return values, e.g. `func (c *C) MergeAccumulators(a, b Acc)` (mutating in place) or `func(a, b int) {}`.

Common situations: Writing a merge method that mutates an accumulator pointer and returns nothing; copying patterns from other frameworks where merges are in-place; accidentally returning nothing after refactoring.

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/fb563d78680abc1d. Report an issue: GitHub.

Appendix: source

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

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

	mergeFn, ok := fn.methods[mergeAccumulatorsName]
	if !ok {
		return nil, errors.Errorf("%v: failed to find required %v method on type: %v", fnKind, mergeAccumulatorsName, fn.Name())
	}

	// CombineFn methods must satisfy the following:
	// CreateAccumulator func() (A, error?)
	// AddInput func(A, I) (A, error?)
	// MergeAccumulators func(A, A) (A, error?)
	// ExtractOutput func(A) (O, error?)
	// This means that the other signatures *must* match the type used in MergeAccumulators.
	if len(mergeFn.Ret) <= 0 {
		return nil, errors.Errorf("%v: %v requires at least 1 return value. : %v", fnKind, mergeAccumulatorsName, mergeFn)
	}
	accumType := mergeFn.Ret[0].T

	for _, mthd := range []struct {
		name    string
		sigFunc func(fx *funcx.Fn, accumType reflect.Type) *funcx.Signature
	}{
		{mergeAccumulatorsName, func(fx *funcx.Fn, accumType reflect.Type) *funcx.Signature {
			return funcx.Replace(mergeAccumulatorsSig, typex.TType, accumType)
		}},
		{createAccumulatorName, func(fx *funcx.Fn, accumType reflect.Type) *funcx.Signature {
			return funcx.Replace(createAccumulatorSig, typex.TType, accumType)
		}},
		{addInputName, func(fx *funcx.Fn, accumType reflect.Type) *funcx.Signature {
			// AddInput needs the last parameter type substituted.
			p := fx.Param[len(fx.Param)-1]
			aiSig := funcx.Replace(addInputSig, typex.TType, accumType)
			return funcx.Replace(aiSig, typex.VType, p.T)

View on GitHub (pinned to 12126d8942)