micro/go-micro · error

subscriber . has wrong number of outs: require signature

Error message

subscriber %v.%v has wrong number of outs: %v require signature %s

What it means

A valid gRPC subscriber handler must return exactly one value of type error, matching the signature `func(ctx context.Context, msg T) error`. validateSubscriber rejects any method whose number of return values is not exactly 1, reporting the actual count via this error.

Solutions

  1. Change the handler to return exactly one value of type error: `func (h *h) Handle(ctx context.Context, evt *Event) error`
  2. If you need to convey results, encode them into the message or use a published response topic instead of extra return values

Example fix

// before
func (h *handler) Handle(ctx context.Context, e *Event) (string, error) { ... }
// after
func (h *handler) Handle(ctx context.Context, e *Event) error { ... }
Defensive patterns

Strategy: validation

Validate before calling

func validHandlerOuts(fn interface{}) bool {
	return reflect.TypeOf(fn).NumOut() == 1
}

Prevention

When it happens

Trigger: Registering a subscriber whose method returns zero values (`func (h *h) Handle(evt *Event)`), two values (`(result, error)`), or more than one output.

Common situations: Copying a request/reply service handler style that returns `(resp, error)`; refactoring handlers to also return a value; forgetting the error return entirely.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/4d68b91d910cc2ef. Report an issue: GitHub.

Appendix: source

Thrown at server/grpc/subscriber.go:156

		hdlr := reflect.ValueOf(sub.Subscriber())
		name := reflect.Indirect(hdlr).Type().Name()

		for m := 0; m < typ.NumMethod(); m++ {
			method := typ.Method(m)

			switch method.Type.NumIn() {
			case 3:
				argType = method.Type.In(2)
			default:
				return fmt.Errorf("subscriber %v.%v takes wrong number of args: %v required signature %s",
					name, method.Name, method.Type.NumIn(), subSig)
			}

			if !isExportedOrBuiltinType(argType) {
				return fmt.Errorf("%v argument type not exported: %v", name, argType)
			}
			if method.Type.NumOut() != 1 {
				return fmt.Errorf(
					"subscriber %v.%v has wrong number of outs: %v require signature %s",
					name, method.Name, method.Type.NumOut(), subSig)
			}
			if returnType := method.Type.Out(0); returnType != typeOfError {
				return fmt.Errorf("subscriber %v.%v returns %v not error", name, method.Name, returnType.String())
			}
		}
	}

	return nil
}

func (g *grpcServer) createSubHandler(sb *subscriber, opts server.Options) broker.Handler {
	return func(p broker.Event) (err error) {
		defer func() {
			if r := recover(); r != nil {
				g.opts.Logger.Log(logger.ErrorLevel, "panic recovered: ", r)
				g.opts.Logger.Log(logger.ErrorLevel, string(debug.Stack()))

View on GitHub (pinned to 24529f1404)