{"record":{"id":"016e144b08395d4d","repo":"hyperledger/fabric","slug":"receiver-t-s-does-not-accept-a-pointer-as-its-ar","errorCode":null,"errorMessage":"receiver %T.%s does not accept a pointer as its argument","messagePattern":"receiver %T\\.(.+?) does not accept a pointer as its argument","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/dispatcher/dispatcher.go","lineNumber":40,"sourceCode":"\n// Dispatch deserializes the input bytes to the correct type for the method in the receiver, then\n// if successful, marshals the output message to bytes and returns it.  On error, it simply returns\n// the error.  The method on the receiver must take a single parameter which is a concrete proto\n// message type and it should return a proto message and error.\nfunc (d *Dispatcher) Dispatch(inputBytes []byte, methodName string, receiver any) ([]byte, error) {\n\tmethod := reflect.ValueOf(receiver).MethodByName(methodName)\n\n\tif method == (reflect.Value{}) {\n\t\treturn nil, errors.Errorf(\"receiver %T.%s does not exist\", receiver, methodName)\n\t}\n\n\tif method.Type().NumIn() != 1 {\n\t\treturn nil, errors.Errorf(\"receiver %T.%s has %d parameters but expected 1\", receiver, methodName, method.Type().NumIn())\n\t}\n\n\tinputType := method.Type().In(0)\n\tif inputType.Kind() != reflect.Pointer {\n\t\treturn nil, errors.Errorf(\"receiver %T.%s does not accept a pointer as its argument\", receiver, methodName)\n\t}\n\n\tif method.Type().NumOut() != 2 {\n\t\treturn nil, errors.Errorf(\"receiver %T.%s returns %d values but expected 2\", receiver, methodName, method.Type().NumOut())\n\t}\n\n\tif !method.Type().Out(0).Implements(reflect.TypeFor[proto.Message]()) {\n\t\treturn nil, errors.Errorf(\"receiver %T.%s does not return a an implementor of proto.Message as its first return value\", receiver, methodName)\n\t}\n\n\tif !method.Type().Out(1).Implements(reflect.TypeFor[error]()) {\n\t\treturn nil, errors.Errorf(\"receiver %T.%s does not return an error as its second return value\", receiver, methodName)\n\t}\n\n\tinputValue := reflect.New(inputType.Elem())\n\tinputMsg, ok := inputValue.Interface().(proto.Message)\n\tif !ok {\n\t\treturn nil, errors.Errorf(\"receiver %T.%s does not accept a proto.Message as its argument, it is '%T'\", receiver, methodName, inputValue.Interface())","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/dispatcher/dispatcher.go#L22-L58","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nfunc (s *AssetSvc) GetAsset(req pb.GetAssetRequest) (*pb.Asset, error) { ... }\n\n// after\nfunc (s *AssetSvc) GetAsset(req *pb.GetAssetRequest) (*pb.Asset, error) { ... }","handlingStrategy":"validation","validationCode":"func validatePointerParam(receiver any, methodName string) error {\n    m := reflect.ValueOf(receiver).MethodByName(methodName)\n    if !m.IsValid() || m.Type().NumIn() != 1 {\n        return fmt.Errorf(\"method %s missing or wrong arity\", methodName)\n    }\n    if m.Type().In(0).Kind() != reflect.Pointer {\n        return fmt.Errorf(\"method %s param must be a pointer\", methodName)\n    }\n    return nil\n}","typeGuard":"func takesPointerParam(receiver any, methodName string) bool {\n    m := reflect.ValueOf(receiver).MethodByName(methodName)\n    if !m.IsValid() || m.Type().NumIn() != 1 {\n        return false\n    }\n    return m.Type().In(0).Kind() == reflect.Pointer\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["go","reflection","proto","contract-violation"],"backgroundTag":"handler-signature-mismatch","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}