micro/go-micro · error
subscriber %v.%v takes wrong number of args: %v required sig
Error message
subscriber %v.%v takes wrong number of args: %v required signature %s
What it means
For struct-based subscribers, every exported method is validated as a handler and must take exactly 3 inputs: receiver, context.Context, and the message (subSig func(context.Context, interface{}) error plus the receiver). validateSubscriber iterates typ.NumMethod() and fails on the first method whose NumIn() != 3, including methods you may not have intended as subscribers.
Source
Thrown at server/grpc/subscriber.go:148
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)
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 nilView on GitHub (pinned to 24529f1404)
Solutions
- Give every exported method on the registered struct the signature (ctx context.Context, msg *T) error.
- Move non-subscriber helpers off the struct or make them unexported (lowercase) so NumMethod doesn't see them.
- Register a dedicated subscriber struct containing only handler methods, separate from your service struct.
- If the handler needs extra config, capture it in the struct's fields (set at construction), not as method parameters.
Example fix
// before
type Handlers struct{}
func (h *Handlers) Handle(ctx context.Context, e *pb.Event, opts ...Option) error { ... }
// after
type Handlers struct{ opts []Option }
func (h *Handlers) Handle(ctx context.Context, e *pb.Event) error { ... } Defensive patterns
Strategy: validation
Validate before calling
func validSubscriberStruct(h interface{}) error {
t := reflect.TypeOf(h)
ctxType := reflect.TypeOf((*context.Context)(nil)).Elem()
errType := reflect.TypeOf((*error)(nil)).Elem()
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
if m.Type.NumIn() != 3 || !m.Type.In(1).Implements(ctxType) || m.Type.NumOut() != 1 || m.Type.Out(0) != errType {
return fmt.Errorf("method %s does not match func(ctx context.Context, msg T) error", m.Name)
}
}
return nil
} Prevention
- Keep handler structs dedicated to subscription methods only.
- Make helpers unexported so reflect.NumMethod skips them.
- Every exported method must be (ctx context.Context, msg *T) error.
- Run validSubscriberStruct on all handler structs in a startup/unit test before subscribing.
When it happens
Trigger: Registering a struct via Subscribe(topic, handlerStruct) where any exported method has the wrong arity, e.g. methods with only (msg *T) error (NumIn 2), or helper/cleanup/exported utility methods with extra parameters (NumIn 4+).
Common situations: Adding a context parameter or extra option to one method on the handler struct; leaving exported helper methods (Health, Close, Configure) on the same struct; value-receiver vs pointer-receiver confusion changing the method set; upgrading go-micro and getting stricter validation than before.
Related errors
- subscriber %v takes wrong number of args: %v required signat
- subscriber %v argument type not exported: %v
- subscriber %v has wrong number of outs: %v require signature
- subscriber %v returns %v not error
- %v argument type not exported: %v
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/1fb04acde7c92aa7.
Report an issue: GitHub.