{"record":{"id":"43fcdc13abf3f03a","repo":"apache/beam","slug":"watermarkestimatorstate-fn-v-has-unexpected-number-of","errorCode":null,"errorMessage":"WatermarkEstimatorState fn %v has unexpected number of parameters: %v","messagePattern":"WatermarkEstimatorState fn (.+?) has unexpected number of parameters: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/runtime/exec/sdf_invokers.go","lineNumber":520,"sourceCode":"\t\t}\n\t\treturn nil\n\t}\n\t// Expects a signature of the form:\n\t// (state) sdf.WatermarkEstimator\n\tswitch fnT := n.fn.Fn.(type) {\n\tcase reflectx.Func1x1:\n\t\tn.call = func(we sdf.WatermarkEstimator) any {\n\t\t\treturn fnT.Call1x1(we)\n\t\t}\n\tdefault:\n\t\tswitch len(n.fn.Param) {\n\t\tcase 1:\n\t\t\tn.call = func(we sdf.WatermarkEstimator) any {\n\t\t\t\tn.args[0] = we\n\t\t\t\treturn n.fn.Fn.Call(n.args)[0]\n\t\t\t}\n\t\tdefault:\n\t\t\treturn errors.Errorf(\"WatermarkEstimatorState fn %v has unexpected number of parameters: %v\",\n\t\t\t\tn.fn.Fn.Name(), len(n.fn.Param))\n\t\t}\n\t}\n\treturn nil\n}\n\n// Invoke calls WatermarkEstimatorState given a restriction and returns an sdf.RTracker.\nfunc (n *wesInvoker) Invoke(we sdf.WatermarkEstimator) any {\n\treturn n.call(we)\n}\n\n// Reset zeroes argument entries in the cached slice to allow values to be\n// garbage collected after the bundle ends.\nfunc (n *wesInvoker) Reset() {\n\tfor i := range n.args {\n\t\tn.args[i] = nil\n\t}\n}","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/exec/sdf_invokers.go#L502-L538","documentation":"The WatermarkEstimatorState accessor function on an SDF must take exactly zero or one parameter (the watermark estimator). initCallFn raises this error when the registered function's parameter count falls outside the supported forms, during invoker initialization.","triggerScenarios":"Registering a WatermarkEstimatorState fn like func(we sdf.WatermarkEstimator, el T) W (2 params) or any other unsupported arity; the invoker builds a call path only for 0 or 1 params and otherwise errors at sdf_invokers.go:520.","commonSituations":"Copy-pasting the estimator method shape from another hook with more parameters, or accidentally adding a second argument when adapting a watermark estimator to a new DoFn.","solutions":["Change WatermarkEstimatorState to take exactly one sdf.WatermarkEstimator parameter.","Use the zero-parameter form if the estimator itself is unnecessary to extract state.","Remove any additional element/restriction parameters from the signature.","Validate the DoFn signature with a unit test that constructs the pipeline before deployment."],"exampleFix":"// before\nfunc (fn *mySdf) WatermarkEstimatorState(we sdf.WatermarkEstimator, ts typex.EventTime) W { ... }\n// after\nfunc (fn *mySdf) WatermarkEstimatorState(we sdf.WatermarkEstimator) W { ... }","handlingStrategy":"validation","validationCode":"t := reflect.TypeOf(fn.WatermarkEstimatorState)\nif t.NumIn() > 1 {\n    return fmt.Errorf(\"WatermarkEstimatorState must take at most 1 parameter, has %d\", t.NumIn())\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"WatermarkEstimatorState fn\") {\n        // reduce to func(we sdf.WatermarkEstimator) W\n    }\n    return err\n}","preventionTips":["Keep WatermarkEstimatorState to exactly one estimator parameter.","Extract extra values inside the function body or from struct fields.","Check signature against sdk docs when upgrading Beam versions."],"tags":["go","beam","sdf","watermark","arity"],"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"}