micro/go-micro · error

subscriber %v takes wrong number of args: %v required signat

Error message

subscriber %v takes wrong number of args: %v required signature %s

What it means

The go-micro gRPC server validates every subscriber registered via Subscribe(). A plain-function subscriber must have the exact signature func(context.Context, interface{}) error — i.e. exactly 2 inputs. This error is thrown when the reflect type check in validateSubscriber sees NumIn() != 2, so the framework refuses to register the handler because it could never be invoked correctly at dispatch time.

Source

Thrown at server/grpc/subscriber.go:125

		topic:      topic,
		subscriber: sub,
		handlers:   handlers,
		endpoints:  endpoints,
		opts:       options,
	}
}

func validateSubscriber(sub server.Subscriber) error {
	typ := reflect.TypeOf(sub.Subscriber())
	var argType reflect.Type

	if typ.Kind() == reflect.Func {
		name := "Func"
		switch typ.NumIn() {
		case 2:
			argType = typ.In(1)
		default:
			return fmt.Errorf("subscriber %v takes wrong number of args: %v required signature %s", name, typ.NumIn(), subSig)
		}
		if !isExportedOrBuiltinType(argType) {
			return fmt.Errorf("subscriber %v argument type not exported: %v", name, argType)
		}
		if typ.NumOut() != 1 {
			return fmt.Errorf("subscriber %v has wrong number of outs: %v require signature %s",
				name, typ.NumOut(), subSig)
		}
		if returnType := typ.Out(0); returnType != typeOfError {
			return fmt.Errorf("subscriber %v returns %v not error", name, returnType.String())
		}
	} else {
		hdlr := reflect.ValueOf(sub.Subscriber())
		name := reflect.Indirect(hdlr).Type().Name()

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

View on GitHub (pinned to 24529f1404)

Solutions

  1. Change the function to exactly func(ctx context.Context, msg *YourType) error (2 inputs).
  2. If you only need the payload, keep 2 args anyway — context is always first; ignore ctx if unused (use _ as the name).
  3. If you intended a multi-method subscriber, register a struct with methods taking (ctx context.Context, msg *T) error instead of a bare func.
  4. Use a named wrapper type so the signature mismatch is caught by the compiler rather than at registration.

Example fix

// before
srv.Subscribe("events", func(e *pb.Event) error { ... })
// after
srv.Subscribe("events", func(ctx context.Context, e *pb.Event) error { ... })
Defensive patterns

Strategy: validation

Validate before calling

func validFuncSub(fn interface{}) bool {
	t := reflect.TypeOf(fn)
	if t == nil || t.Kind() != reflect.Func || t.NumIn() != 2 {
		return false
	}
	ctxType := reflect.TypeOf((*context.Context)(nil)).Elem()
	return t.In(0).Implements(ctxType)
}

Type guard

func asEventFunc(fn interface{}) func(context.Context, interface{}) error {
	f, ok := fn.(func(context.Context, interface{}) error)
	if !ok { return nil }
	return f
}

Prevention

When it happens

Trigger: Calling server.Subscribe(topic, fn) where fn is a func literal with 0, 1, or 3+ input parameters, e.g. func(msg *pb.Event) error (1 arg, missing ctx) or func(ctx context.Context, msg *pb.Event, extra string) error (3 args).

Common situations: Copy-pasting a handler written for another framework that passes only the message; adding a helper parameter to a working handler; using a method-style handler signature as a bare func; refactoring that swapped argument order or dropped context.

Related errors


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