{"record":{"id":"f49baefcf4c50fa6","repo":"geektutu/7days-golang","slug":"rpc-server-service-method-request-ill-formed-f49bae","errorCode":null,"errorMessage":"rpc server: service/method request ill-formed: ","messagePattern":"rpc server: service/method request ill-formed: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gee-rpc/day6-load-balance/server.go","lineNumber":116,"sourceCode":"\tmtype        *methodType\n\tsvc          *service\n}\n\nfunc (server *Server) readRequestHeader(cc codec.Codec) (*codec.Header, error) {\n\tvar h codec.Header\n\tif err := cc.ReadHeader(&h); err != nil {\n\t\tif err != io.EOF && err != io.ErrUnexpectedEOF {\n\t\t\tlog.Println(\"rpc server: read header error:\", err)\n\t\t}\n\t\treturn nil, err\n\t}\n\treturn &h, nil\n}\n\nfunc (server *Server) findService(serviceMethod string) (svc *service, mtype *methodType, err error) {\n\tdot := strings.LastIndex(serviceMethod, \".\")\n\tif dot < 0 {\n\t\terr = errors.New(\"rpc server: service/method request ill-formed: \" + serviceMethod)\n\t\treturn\n\t}\n\tserviceName, methodName := serviceMethod[:dot], serviceMethod[dot+1:]\n\tsvci, ok := server.serviceMap.Load(serviceName)\n\tif !ok {\n\t\terr = errors.New(\"rpc server: can't find service \" + serviceName)\n\t\treturn\n\t}\n\tsvc = svci.(*service)\n\tmtype = svc.method[methodName]\n\tif mtype == nil {\n\t\terr = errors.New(\"rpc server: can't find method \" + methodName)\n\t}\n\treturn\n}\n\nfunc (server *Server) readRequest(cc codec.Codec) (*request, error) {\n\th, err := server.readRequestHeader(cc)","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-rpc/day6-load-balance/server.go#L98-L134","documentation":"Server.findService parses the \"ServiceName.MethodName\" string sent by the client. This error is returned when the string contains no dot separator, so it cannot be split into a service and method part. The library requires the Go RPC convention of \"Service.Method\" in every request header.","triggerScenarios":"Client calls Call()/Go() with a serviceMethod string lacking a dot, e.g. \"Foo\" instead of \"Foo.Bar\", or an empty/whitespace-only method string.","commonSituations":"Typos in the method path, building the serviceMethod string with concatenation or sprintf that drops the dot, passing just a method name when wrapping the client, or an older client version using a different naming scheme.","solutions":["Pass the full \"Service.Method\" string to xdial/Client.Call, e.g. \"Foo.Sum\" instead of \"Sum\".","Log the incoming serviceMethod on the server to confirm what the client actually sent.","Keep service and method names in shared constants so client and server agree on the format."],"exampleFix":"// before\nclient.Call(ctx, \"Sum\", req, reply)\n// after\nclient.Call(ctx, \"Foo.Sum\", req, reply)","handlingStrategy":"validation","validationCode":"if !strings.Contains(serviceMethod, \".\") || serviceMethod == \"\" {\n    return fmt.Errorf(\"serviceMethod must be \\\"Service.Method\\\", got %q\", serviceMethod)\n}","typeGuard":null,"tryCatchPattern":"if err := client.Call(ctx, serviceMethod, args, reply); err != nil && strings.Contains(err.Error(), \"ill-formed\") { /* fix call-site naming */ }","preventionTips":["Define serviceMethod strings as shared constants like const FooSum = \"Foo.Sum\".","Never build method paths with manual concatenation without a dot.","Write a unit test asserting every call path matches ^[A-Za-z0-9_]+\\.[A-Za-z0-9_]+$."],"tags":["rpc","request-format","protocol"],"backgroundTag":"malformed-rpc-service-method","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}