{"record":{"id":"843c686bac7e7e0b","repo":"hyperledger/fabric","slug":"receiver-t-s-does-not-exist","errorCode":null,"errorMessage":"receiver %T.%s does not exist","messagePattern":"receiver %T\\.(.+?) does not exist","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/dispatcher/dispatcher.go","lineNumber":31,"sourceCode":"\t\"google.golang.org/protobuf/proto\"\n)\n\n// Dispatcher is used to handle the boilerplate proto tasks of unmarshalling inputs and remarshaling outputs\n// so that the receiver may focus on the implementation details rather than the proto hassles.\ntype Dispatcher struct {\n\t// Protobuf should pass through to Google Protobuf in production paths\n\tProtobuf Protobuf\n}\n\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}","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/dispatcher/dispatcher.go#L13-L49","documentation":"Dispatcher.Dispatch uses reflection (MethodByName) to locate a method on the receiver and returns this error when no such method exists. It is the dispatcher's way of reporting an unknown RPC/invocation target before any parameter or proto validation happens.","triggerScenarios":"Dispatch(inputBytes, methodName, receiver) is called with a methodName that the receiver type does not expose, or the receiver registered for the invocation path does not implement the expected method set (e.g. Invoke dispatches to a handler missing the method).","commonSituations":"Chaincode/lifecycle handlers renamed or missing between versions; typo'd method name in the invocation request; wrong receiver struct wired into the dispatcher; a client invoking a system chaincode method not present in the deployed binary.","solutions":["Verify methodName matches an exported, pointer-receiver method on the receiver type (case-sensitive)","Ensure the correct receiver implementation is registered for this invocation path and that both orderer/peer binaries are the same version","Add the missing method to the receiver or correct the caller's method name","Add a registry/compile-time check that all dispatched method names exist on their receivers"],"exampleFix":"// before\ndispatcher.Dispatch(inputBytes, \"DeployLablock\", handler) // typo\n// after\ndispatcher.Dispatch(inputBytes, \"DeployChaincode\", handler)","handlingStrategy":"validation","validationCode":"m := reflect.ValueOf(receiver).MethodByName(methodName)\nif !m.IsValid() {\n    return fmt.Errorf(\"method %s not implemented by %T\", methodName, receiver)\n}","typeGuard":"func receiverHasMethod(receiver any, name string) bool {\n    return reflect.ValueOf(receiver).MethodByName(name).IsValid()\n}","tryCatchPattern":"out, err := dispatcher.Dispatch(inputBytes, methodName, receiver)\nif err != nil {\n    if strings.Contains(err.Error(), \"does not exist\") {\n        return status.Errorf(codes.NotFound, \"unknown method %s\", methodName)\n    }\n    return err\n}","preventionTips":["Keep method-name constants shared between client and handler instead of raw strings","Add unit tests that reflect over each receiver and assert all dispatched methods exist","Pin peer/orderer versions so handler method sets stay in sync"],"tags":["reflection","dispatch","method-not-found","hyperledger-fabric"],"backgroundTag":"method-not-found","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"}