{"record":{"id":"06d2c3c652c23200","repo":"apache/beam","slug":"invalid-output-type-in-method-v-return-value-at-index-v-type-06d2c3","errorCode":null,"errorMessage":"invalid output type in method %v, return value at index %v (type: %v). Output of method %v must implement sdf.WatermarkEstimator.","messagePattern":"invalid output type in method (.+?), return value at index (.+?) \\(type: (.+?)\\)\\. Output of method (.+?) must implement sdf\\.WatermarkEstimator\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/graph/fn.go","lineNumber":1213,"sourceCode":"\t\t\terr := errors.Errorf(\"stateful watermark estimation method %v is present, \"+\n\t\t\t\t\"but CreateWatermarkEstimator doesn't take in a state parameter.\", initialWatermarkEstimatorStateName)\n\t\t\treturn err\n\t\t}\n\t\tif _, ok := fn.methods[watermarkEstimatorStateName]; ok {\n\t\t\terr := errors.Errorf(\"stateful watermark estimation method %v is present, \"+\n\t\t\t\t\"but CreateWatermarkEstimator doesn't take in a state parameter.\", watermarkEstimatorStateName)\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif len(method.Ret) != returnNum {\n\t\terr := errors.Errorf(\"unexpected number of returns in method %v. got: %v, want: %v\",\n\t\t\tcreateWatermarkEstimatorName, len(method.Ret), returnNum)\n\t\treturn errors.SetTopLevelMsgf(err, \"unexpected number of return values in method %v. \"+\n\t\t\t\"got: %v, want: %v. Check that the signature conforms to the expected signature for %v.\",\n\t\t\tcreateWatermarkEstimatorName, len(method.Ret), returnNum, createWatermarkEstimatorName)\n\t} else if !method.Ret[0].T.Implements(watermarkEstimatorT) {\n\t\terr := errors.Errorf(\"invalid output type in method %v, return %v: %v does not implement sdf.WatermarkEstimator\",\n\t\t\tcreateWatermarkEstimatorName, 0, method.Ret[0].T)\n\t\treturn errors.SetTopLevelMsgf(err, \"invalid output type in method %v, \"+\n\t\t\t\"return value at index %v (type: %v). Output of method %v must implement sdf.WatermarkEstimator.\",\n\t\t\tcreateWatermarkEstimatorName, 0, method.Ret[0].T, createWatermarkEstimatorName)\n\t}\n\n\tprocessFn := fn.methods[processElementName]\n\tpos, _ := processFn.WatermarkEstimator()\n\tif pos != -1 && method.Ret[0].T != processFn.Param[pos].T {\n\t\terr := errors.Errorf(\"mismatched output type in method %v, return %v: got: %v, want: %v\",\n\t\t\twatermarkEstimatorStateName, 0, method.Ret[0].T, processFn.Param[pos].T)\n\t\treturn errors.SetTopLevelMsgf(err, \"Mismatched output type in method %v, \"+\n\t\t\t\"return value at index %v. Got: %v, Want: %v (from method %v).\",\n\t\t\twatermarkEstimatorStateName, 0, method.Ret[0].T, processFn.Param[pos].T, processElementName)\n\t}\n\n\treturn nil\n}","sourceCodeStart":1195,"sourceCodeEnd":1231,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/fn.go#L1195-L1231","documentation":"During validation of a Beam Go SDF (Splittable DoFn), the CreateWatermarkEstimator method must return exactly one value implementing sdf.WatermarkEstimator. This error is raised when the first return value's type does not implement that interface. Beam checks this at graph-construction time so bad DoFn signatures fail fast before pipeline execution.","triggerScenarios":"Defining an SDF whose CreateWatermarkEstimator() method returns a concrete type (or pointer) that does not implement sdf.WatermarkEstimator, e.g. returning a custom struct without a Watermark() typex.EventTime method, or returning a value type when the interface methods are on a pointer receiver.","commonSituations":"Hand-writing an SDF copied from an example but renaming the estimator type; implementing Watermark() with a wrong signature; returning the estimator by value when methods are defined on pointer receiver; upgrading Beam where the WatermarkEstimator interface gained methods.","solutions":["Make the CreateWatermarkEstimator return value implement sdf.WatermarkEstimator: it needs method Watermark() typex.EventTime.","Check whether Watermark() is defined on a pointer receiver while the method returns a value type (or the reverse); make the return type match the receiver type.","If doing stateful estimation, return a state-aware estimator type instead of a plain value.","Verify against the current Beam SDK version's sdf.WatermarkEstimator interface in case the interface surface changed."],"exampleFix":"// before\nfunc (f *fn) CreateWatermarkEstimator(rest MyRestriction) int64 {\n    return 0\n}\n// after\nfunc (f *fn) CreateWatermarkEstimator(rest MyRestriction) sdf.WatermarkEstimator {\n    return &myWatermarkEstimator{watermark: typex.MinTimestamp}\n}\n// with\ntype myWatermarkEstimator struct{ watermark typex.EventTime }\nfunc (e *myWatermarkEstimator) Watermark() typex.EventTime { return e.watermark }","handlingStrategy":"validation","validationCode":"var _ sdf.WatermarkEstimator = (*myWatermarkEstimator)(nil)\nvar _ func(MyRestriction) sdf.WatermarkEstimator = (*fn).CreateWatermarkEstimator","typeGuard":"func implementsWatermarkEstimator(v any) bool {\n    _, ok := v.(sdf.WatermarkEstimator)\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Assert interface satisfaction at compile time with var _ sdf.WatermarkEstimator = (*T)(nil).","Keep the Watermark() receiver type identical to the CreateWatermarkEstimator return type.","Copy signatures from an up-to-date Beam SDF example rather than from memory.","Run graph validation early in tests; these errors surface before any data flows."],"tags":["go","apache-beam","sdf","watermark-estimator","type-mismatch"],"backgroundTag":"type-mismatch","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"}