{"record":{"id":"cab4573ac3504ca9","repo":"apache/beam","slug":"first-main-input-parameter-must-be-a-value-type","errorCode":null,"errorMessage":"first main input parameter must be a value type","messagePattern":"first main input parameter must be a value type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/graph/fn.go","lineNumber":680,"sourceCode":"\t\terr = errors.SetTopLevelMsgf(err,\n\t\t\t\"Method %v in DoFn %v is missing all inputs. A main input is required.\",\n\t\t\tmethodName, fn.Name())\n\t\treturn err\n\t}\n\tif num < int(numMainIn) {\n\t\terr := errors.Errorf(\"%v method has too few main inputs\", methodName)\n\t\terr = errors.SetTopLevelMsgf(err,\n\t\t\t\"Method %v in DoFn %v does not have enough main inputs. \"+\n\t\t\t\t\"%v main inputs were expected, but only %v inputs were found.\",\n\t\t\tmethodName, fn.Name(), numMainIn, num)\n\t\treturn err\n\t}\n\n\t// Check that the first input is not an Iter or ReIter (those aren't valid\n\t// as the first main input).\n\tfirst := method.Param[pos].Kind\n\tif first != funcx.FnValue {\n\t\terr := errors.New(\"first main input parameter must be a value type\")\n\t\terr = errors.SetTopLevelMsgf(err,\n\t\t\t\"Method %v of DoFns should always have the first input be a value type, \"+\n\t\t\t\t\"but it has an Iter or ReIter first in DoFn %v.\",\n\t\t\tprocessElementName, fn.Name())\n\t\treturn errors.WithContextf(err, \"method %v\", processElementName)\n\t}\n\treturn nil\n}\n\n// validateEmits compares the emits found in a DoFn method signature with the emits found in\n// the signature for ProcessElement, and performs validation that those match. This function\n// should only be used to validate methods that are expected to have the same emit parameters as\n// ProcessElement.\nfunc validateEmits(processFnEmits []funcx.FnParam, method *funcx.Fn, methodName string) error {\n\tposMethodEmits, numMethodEmits, ok := method.Emits()\n\tnumProcessEmits := len(processFnEmits)\n\n\t// Handle cases where method has no emits.","sourceCodeStart":662,"sourceCodeEnd":698,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/fn.go#L662-L698","documentation":"When validating a DoFn (AsDoFn -> validateMainInputs), Beam requires the first main input parameter of ProcessElement to be a plain value (FnValue). Iterators (Iter) or re-iterators (ReIter) cannot be the first main input because the framework must hand the element itself before any iterable view.","triggerScenarios":"Declaring ProcessElement with an iterator parameter before the element, e.g. `ProcessElement(iter func(func(int) bool), v string)` where both are main inputs, or restructuring signatures so an Iter/ReIter precedes the element value.","commonSituations":"DoFns adapted from group-by-key patterns where whole-group iteration was intended but written as the first main input; porting from other SDKs where element iteration order is flexible.","solutions":["Reorder ProcessElement parameters so a value-typed element comes first; put Iter/ReIter parameters after it.","If the intent is full-group iteration, use a value parameter of a slice/KV type instead of an Iter as the first input.","For GBK results, accept the CoGBK result type properly (KV<K, Iter<V>>) rather than a bare Iter main input.","Use a side input if the iterable is a side view rather than a main input."],"exampleFix":"// before\nfunc (fn *f) ProcessElement(it func(func(int) bool), k string) {}\n// after\nfunc (fn *f) ProcessElement(k string, it func(func(int) bool)) {}","handlingStrategy":"validation","validationCode":"func firstMainInputIsValue(fn reflect.Type, skip int) bool {\n    return fn.In(skip).Kind() != reflect.Ptr || reflect.TypeOf(typex.EventTime(0)) != fn.In(skip).Elem()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always place the element value first in ProcessElement; iterators come after.","Use CoGBK result types (KV<K, Iter<V>>) for whole-group processing instead of bare Iter first inputs.","Run graph-construction tests that invoke AsDoFn on all DoFns before deploying."],"tags":["go","beam","dofn","signature-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}