hyperledger/fabric · error
receiver %T.%s does not accept a pointer as its argument
Error message
receiver %T.%s does not accept a pointer as its argument
What it means
Dispatch requires the single input parameter to be a pointer (reflect.Pointer kind) because it allocates the message with reflect.New(inputType.Elem()) and unmarshals the input bytes into it. This error is thrown when the method's one parameter is a value type, which the dispatcher cannot populate from bytes.
Source
Thrown at core/dispatcher/dispatcher.go:40
// Dispatch deserializes the input bytes to the correct type for the method in the receiver, then
// if successful, marshals the output message to bytes and returns it. On error, it simply returns
// the error. The method on the receiver must take a single parameter which is a concrete proto
// message type and it should return a proto message and error.
func (d *Dispatcher) Dispatch(inputBytes []byte, methodName string, receiver any) ([]byte, error) {
method := reflect.ValueOf(receiver).MethodByName(methodName)
if method == (reflect.Value{}) {
return nil, errors.Errorf("receiver %T.%s does not exist", receiver, methodName)
}
if method.Type().NumIn() != 1 {
return nil, errors.Errorf("receiver %T.%s has %d parameters but expected 1", receiver, methodName, method.Type().NumIn())
}
inputType := method.Type().In(0)
if inputType.Kind() != reflect.Pointer {
return nil, errors.Errorf("receiver %T.%s does not accept a pointer as its argument", receiver, methodName)
}
if method.Type().NumOut() != 2 {
return nil, errors.Errorf("receiver %T.%s returns %d values but expected 2", receiver, methodName, method.Type().NumOut())
}
if !method.Type().Out(0).Implements(reflect.TypeFor[proto.Message]()) {
return nil, errors.Errorf("receiver %T.%s does not return a an implementor of proto.Message as its first return value", receiver, methodName)
}
if !method.Type().Out(1).Implements(reflect.TypeFor[error]()) {
return nil, errors.Errorf("receiver %T.%s does not return an error as its second return value", receiver, methodName)
}
inputValue := reflect.New(inputType.Elem())
inputMsg, ok := inputValue.Interface().(proto.Message)
if !ok {
return nil, errors.Errorf("receiver %T.%s does not accept a proto.Message as its argument, it is '%T'", receiver, methodName, inputValue.Interface())View on GitHub (pinned to 2736b63f8f)
Solutions
- Change the parameter to a pointer to the proto message: func (s *Svc) Do(req *pb.Request) (*pb.Response, error).
- Always use the canonical pointer form for generated proto message types, matching the protobuf-go API.
Example fix
// before
func (s *AssetSvc) GetAsset(req pb.GetAssetRequest) (*pb.Asset, error) { ... }
// after
func (s *AssetSvc) GetAsset(req *pb.GetAssetRequest) (*pb.Asset, error) { ... } Defensive patterns
Strategy: validation
Validate before calling
func validatePointerParam(receiver any, methodName string) error {
m := reflect.ValueOf(receiver).MethodByName(methodName)
if !m.IsValid() || m.Type().NumIn() != 1 {
return fmt.Errorf("method %s missing or wrong arity", methodName)
}
if m.Type().In(0).Kind() != reflect.Pointer {
return fmt.Errorf("method %s param must be a pointer", methodName)
}
return nil
} Type guard
func takesPointerParam(receiver any, methodName string) bool {
m := reflect.ValueOf(receiver).MethodByName(methodName)
if !m.IsValid() || m.Type().NumIn() != 1 {
return false
}
return m.Type().In(0).Kind() == reflect.Pointer
} Prevention
- Always declare proto parameters as pointers: *pb.Request, never pb.Request.
- Add a signature-contract check to CI for all dispatched handler methods.
- Keep handler signatures uniform so the pointer form becomes habit.
When it happens
Trigger: Calling Dispatch (via Invoke) on a method declared as func (s *Svc) Do(req pb.Request) (...) — the proto message passed by value instead of *pb.Request.
Common situations: Developers new to protobuf-go write value parameters since messages are plain structs; refactors from hand-written interfaces where value semantics were acceptable; copy-paste from non-proto Go code.
Related errors
- receiver %T.%s has %d parameters but expected 1
- receiver %T.%s returns %d values but expected 2
- receiver %T.%s does not return a an implementor of proto.Mes
- receiver %T.%s does not return an error as its second return
- message of type %s unknown
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/016e144b08395d4d.
Report an issue: GitHub.