{"record":{"id":"ca64b2994a0890cd","repo":"apache/beam","slug":"unexpected-number-of-returns-in-method-v-got-v-want-v-or","errorCode":null,"errorMessage":"unexpected number of returns in method %v. got: %v, want: %v or optionally %v if last value is of type error","messagePattern":"unexpected number of returns in method (.+?)\\. got: (.+?), want: (.+?) or optionally (.+?) if last value is of type error","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/graph/fn.go","lineNumber":965,"sourceCode":"\n\tfor _, name := range sdfNames {\n\t\tmethod, ok := fn.methods[name]\n\t\tif !ok && optionalSdfs[name] {\n\t\t\tcontinue\n\t\t}\n\n\t\treqParamNum := reqParamNums[name]\n\t\tif !sdfHasValidParamNum(method.Param, reqParamNum) {\n\t\t\terr := errors.Errorf(\"unexpected number of params in method %v. got: %v, want: %v or optionally %v \"+\n\t\t\t\t\"if first param is of type context.Context\", name, len(method.Param), reqParamNum, reqParamNum+1)\n\t\t\treturn errors.SetTopLevelMsgf(err, \"Unexpected number of parameters in method %v. \"+\n\t\t\t\t\"Got: %v, Want: %v or optionally %v if first param is of type context.Context. \"+\n\t\t\t\t\"Check that the signature conforms to the expected signature for %v, and that elements in SDF method \"+\n\t\t\t\t\"parameters match elements in %v.\", name, len(method.Param), reqParamNum, reqParamNum+1,\n\t\t\t\tname, processElementName)\n\t\t}\n\t\tif !sdfHasValidReturnNum(method.Ret, reqReturnNum) {\n\t\t\terr := errors.Errorf(\"unexpected number of returns in method %v. got: %v, want: %v or optionally %v \"+\n\t\t\t\t\"if last value is of type error\", name, len(method.Ret), reqReturnNum, reqReturnNum+1)\n\t\t\treturn errors.SetTopLevelMsgf(err, \"Unexpected number of return values in method %v. \"+\n\t\t\t\t\"Got: %v, Want: %v or optionally %v if last value is of type error. \"+\n\t\t\t\t\"Check that the signature conforms to the expected signature for %v.\",\n\t\t\t\tname, len(method.Ret), reqReturnNum, reqReturnNum+1, name)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc sdfHasValidParamNum(params []funcx.FnParam, requiredNum int) bool {\n\tif len(params) == requiredNum {\n\t\treturn true\n\t}\n\n\treturn len(params) == requiredNum+1 && params[0].Kind == funcx.FnContext\n}\n","sourceCodeStart":947,"sourceCodeEnd":983,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/fn.go#L947-L983","documentation":"validateSdfSigNumbers also validates return-value counts for SDF methods: each method must return the required number of values, optionally plus a trailing error. This error is thrown when method.Ret has neither reqReturnNum nor reqReturnNum+1 values where the extra last value is of type error.","triggerScenarios":"An SDF method returning no value when one is required (e.g. CreateInitialRestriction returning nothing), or returning two non-error values, or returning error first instead of last.","commonSituations":"Writing ProcessElement without returning the emitted element(s); returning a restriction plus error in CreateInitialRestriction; Go beginners adding an error return out of habit in the wrong position.","solutions":["Change the method to return exactly the required values, optionally followed by one trailing error.","For CreateInitialRestriction/SplitRestriction/CreateTracker, remove extra return values or add the missing restriction/tracker return.","If returning an error, make sure it is the LAST return value.","Consult the expected return shape for the named method (reported in the error) in sdks/go/pkg/beam/core/graph/fn.go."],"exampleFix":"// before\nfunc (fn *myFn) CreateInitialRestriction(elem string) error { ... }\n\n// after\nfunc (fn *myFn) CreateInitialRestriction(elem string) myRestriction { ... }","handlingStrategy":"validation","validationCode":"// Validate return counts (allowing optional trailing error) before registration:\nfunc checkReturnCount(t reflect.Type, name string, want int) error {\n    m, ok := t.MethodByName(name)\n    if !ok { return fmt.Errorf(\"missing method %s\", name) }\n    n := m.Type.NumOut()\n    errT := reflect.TypeOf((*error)(nil)).Elem()\n    if n == want || (n == want+1 && m.Type.Out(n-1) == errT) { return nil }\n    return fmt.Errorf(\"%s: got %d returns, want %d (+optional trailing error)\", name, n, want)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Return error last, only when needed","Match each SDF method to its documented return shape","Build pipelines in tests so signature errors surface in CI"],"tags":["go","apache-beam","sdf","signature-validation","reflection"],"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-14T16:17:12.679Z"}