{"record":{"id":"798d508fe614e8ad","repo":"apache/beam","slug":"v-failed-to-find-required-v-method-on-type-v","errorCode":null,"errorMessage":"%v: failed to find required %v method on type: %v","messagePattern":"(.+?): failed to find required (.+?) method on type: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/graph/fn.go","lineNumber":1527,"sourceCode":"\tif err != nil {\n\t\treturn nil, errors.WithContext(errors.Wrapf(err, \"invalid CombineFn\"), \"constructing CombineFn\")\n\t}\n\treturn AsCombineFn(ret)\n}\n\n// AsCombineFn converts a Fn to a CombineFn, if possible.\nfunc AsCombineFn(fn *Fn) (*CombineFn, error) {\n\tconst fnKind = \"graph.AsCombineFn\"\n\tif fn.methods == nil {\n\t\tfn.methods = make(map[string]*funcx.Fn)\n\t}\n\tif fn.Fn != nil {\n\t\tfn.methods[mergeAccumulatorsName] = fn.Fn\n\t}\n\n\tmergeFn, ok := fn.methods[mergeAccumulatorsName]\n\tif !ok {\n\t\treturn nil, errors.Errorf(\"%v: failed to find required %v method on type: %v\", fnKind, mergeAccumulatorsName, fn.Name())\n\t}\n\n\t// CombineFn methods must satisfy the following:\n\t// CreateAccumulator func() (A, error?)\n\t// AddInput func(A, I) (A, error?)\n\t// MergeAccumulators func(A, A) (A, error?)\n\t// ExtractOutput func(A) (O, error?)\n\t// This means that the other signatures *must* match the type used in MergeAccumulators.\n\tif len(mergeFn.Ret) <= 0 {\n\t\treturn nil, errors.Errorf(\"%v: %v requires at least 1 return value. : %v\", fnKind, mergeAccumulatorsName, mergeFn)\n\t}\n\taccumType := mergeFn.Ret[0].T\n\n\tfor _, mthd := range []struct {\n\t\tname    string\n\t\tsigFunc func(fx *funcx.Fn, accumType reflect.Type) *funcx.Signature\n\t}{\n\t\t{mergeAccumulatorsName, func(fx *funcx.Fn, accumType reflect.Type) *funcx.Signature {","sourceCodeStart":1509,"sourceCodeEnd":1545,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/fn.go#L1509-L1545","documentation":"Every CombineFn must define a MergeAccumulators method (or the passed function must be a merge-accumulators-style function). AsCombineFn looks up fn.methods[mergeAccumulatorsName]; when it's absent it fails with this error naming the fn kind (e.g. 'combineFn' or 'funType') and the type name.","triggerScenarios":"Passing a struct to beam.Combine that defines CreateAccumulator/AddInput/ExtractOutput but no exported MergeAccumulators method.","commonSituations":"Misspelling the method (MergeAccumulator, MergeAccumulatorsFn); defining it unexported (mergeAccumulators); implementing only some methods when migrating from a plain func to a CombineFn struct.","solutions":["Add an exported MergeAccumulators method: `func (fn *MyCombine) MergeAccumulators(a, b MyAccum) MyAccum`.","Fix method-name spelling/casing to exactly MergeAccumulators.","If combining with a plain function, use a signature of the form `func(A, A) A` (merge-only).","Check fn.Name() in the error message to confirm you're validating the intended type."],"exampleFix":"// before: missing method\nfunc (c *Sum) CreateAccumulator() int { return 0 }\nfunc (c *Sum) AddInput(a, i int) int { return a + i }\n// after\nfunc (c *Sum) MergeAccumulators(a, b int) int { return a + b }","handlingStrategy":"validation","validationCode":"if reflect.ValueOf(myCombine).MethodByName(\"MergeAccumulators\").IsZero() {\n    panic(\"MyCombine must define exported MergeAccumulators\")\n}","typeGuard":"func hasMergeAccumulators(v interface{}) bool {\n    return !reflect.ValueOf(v).MethodByName(\"MergeAccumulators\").IsZero()\n}","tryCatchPattern":null,"preventionTips":["Always define MergeAccumulators first when writing a CombineFn.","Keep method names exactly exported: MergeAccumulators, CreateAccumulator, AddInput, ExtractOutput."],"tags":["beam","go","combinefn","missing-method"],"backgroundTag":"missing-required-argument","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}