{"record":{"id":"0d25bd841faeaf1b","repo":"micro/go-micro","slug":"subscriber-v-has-wrong-number-of-outs-v-require","errorCode":null,"errorMessage":"subscriber %v has wrong number of outs: %v require signature %s","messagePattern":"subscriber (.+?) has wrong number of outs: (.+?) require signature (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/grpc/subscriber.go","lineNumber":131,"sourceCode":"}\n\nfunc validateSubscriber(sub server.Subscriber) error {\n\ttyp := reflect.TypeOf(sub.Subscriber())\n\tvar argType reflect.Type\n\n\tif typ.Kind() == reflect.Func {\n\t\tname := \"Func\"\n\t\tswitch typ.NumIn() {\n\t\tcase 2:\n\t\t\targType = typ.In(1)\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"subscriber %v takes wrong number of args: %v required signature %s\", name, typ.NumIn(), subSig)\n\t\t}\n\t\tif !isExportedOrBuiltinType(argType) {\n\t\t\treturn fmt.Errorf(\"subscriber %v argument type not exported: %v\", name, argType)\n\t\t}\n\t\tif typ.NumOut() != 1 {\n\t\t\treturn fmt.Errorf(\"subscriber %v has wrong number of outs: %v require signature %s\",\n\t\t\t\tname, typ.NumOut(), subSig)\n\t\t}\n\t\tif returnType := typ.Out(0); returnType != typeOfError {\n\t\t\treturn fmt.Errorf(\"subscriber %v returns %v not error\", name, returnType.String())\n\t\t}\n\t} else {\n\t\thdlr := reflect.ValueOf(sub.Subscriber())\n\t\tname := reflect.Indirect(hdlr).Type().Name()\n\n\t\tfor m := 0; m < typ.NumMethod(); m++ {\n\t\t\tmethod := typ.Method(m)\n\n\t\t\tswitch method.Type.NumIn() {\n\t\t\tcase 3:\n\t\t\t\targType = method.Type.In(2)\n\t\t\tdefault:\n\t\t\t\treturn fmt.Errorf(\"subscriber %v.%v takes wrong number of args: %v required signature %s\",\n\t\t\t\t\tname, method.Name, method.Type.NumIn(), subSig)","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/server/grpc/subscriber.go#L113-L149","documentation":"A subscriber function must return exactly one value: error (signature func(context.Context, interface{}) error). validateSubscriber rejects handlers whose return count differs from 1, because the dispatch code (createSubHandler) reads returnValues[0] unconditionally and needs an error to decide ack/retry behavior.","triggerScenarios":"Registering a func with zero returns (func(ctx context.Context, e *T)) or multiple returns (func(ctx context.Context, e *T) (bool, error)), or a method-style subscriber method on a struct returning something other than exactly one error.","commonSituations":"Reusing an ordinary service method that returns (result, error) as a subscriber; stripping the error return to 'simplify' the handler; adapting a callback that logs instead of returning errors; converting handlers between frameworks with different conventions.","solutions":["Give the handler exactly one return value of type error.","If you need to surface results, publish them on another topic or store them — subscribers communicate via errors only.","If the handler can't fail, still return nil error: func(ctx context.Context, e *T) error { ...; return nil }.","Move multi-value logic into an inner helper and wrap it in a signature-compliant subscriber."],"exampleFix":"// before\nsrv.Subscribe(\"events\", func(ctx context.Context, e *pb.Event) (bool, error) { ... })\n// after\nsrv.Subscribe(\"events\", func(ctx context.Context, e *pb.Event) error { ...; return nil })","handlingStrategy":"validation","validationCode":"func singleErrorReturn(fn interface{}) bool {\n\tt := reflect.TypeOf(fn)\n\treturn t != nil && t.Kind() == reflect.Func && t.NumOut() == 1 &&\n\t\tt.Out(0) == reflect.TypeOf((*error)(nil)).Elem()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Subscribers return exactly one value: error — no exceptions.","Discard intermediate results; publish outcomes on another topic instead.","Return nil error even for infallible handlers.","Lint handler registrations with the reflect-based validation helper in tests."],"tags":["go","grpc","subscriber","handler-signature","return-values"],"backgroundTag":"invalid-handler-signature","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}