{"record":{"id":"0277353117a3f0a0","repo":"apache/dolphinscheduler","slug":"grpc-task-method-name-is-invalid","errorCode":null,"errorMessage":"grpc task method name is invalid","messagePattern":"grpc task method name is invalid","errorType":"validation","errorClass":"GrpcParserException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-task-plugin/dolphinscheduler-task-grpc/src/main/java/org/apache/dolphinscheduler/plugin/task/grpc/protobufjs/GrpcDynamicService.java","lineNumber":150,"sourceCode":"                && !methodDesc.isClientStreaming()) {\n            return MethodDescriptor.MethodType.SERVER_STREAMING;\n        } else if (!methodDesc.isServerStreaming()) {\n            return MethodDescriptor.MethodType.CLIENT_STREAMING;\n        } else {\n            return MethodDescriptor.MethodType.BIDI_STREAMING;\n        }\n    }\n\n    public static class MethodName {\n\n        @Getter\n        String serviceName = null;\n        @Getter\n        String rpcName = null;\n\n        public MethodName(String methodNameWithService) {\n            if (!checkMethodName(methodNameWithService))\n                throw new GrpcParserException(\"grpc task method name is invalid\");\n        }\n\n        private boolean checkMethodName(String methodNameWithService) {\n            String[] path = methodNameWithService.split(GrpcConstants.SERVICE_METHOD_SEPERATOR);\n            if (path.length == 0)\n                return false;\n            if (path.length == 1)\n                rpcName = path[0];\n            if (path.length == 2) {\n                serviceName = path[0];\n                rpcName = path[1];\n            } else {\n                return false;\n            }\n            if (serviceName == null || serviceName.isEmpty()) {\n                return false;\n            }\n            return rpcName != null && !rpcName.isEmpty();","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-task-plugin/dolphinscheduler-task-grpc/src/main/java/org/apache/dolphinscheduler/plugin/task/grpc/protobufjs/GrpcDynamicService.java#L132-L168","documentation":"MethodName parses the task's method identifier string in the form '<serviceName>.<rpcName>' (split on GrpcConstants.SERVICE_METHOD_SEPERATOR). If the string does not split into exactly one or two non-empty parts, the constructor throws GrpcParserException('grpc task method name is invalid') without constructing a service/rpc pair. Note the check is structural: a well-formed-looking name can still pass and fail later with 'cannot find service/method'.","triggerScenarios":"Passing a methodNameWithService to call() or mergeJSON() that is null/empty, contains more than one separator (e.g. 'a.b.c'), or contains only the separator ('.'), or has an empty service or rpc part (e.g. '.SayHello', 'Greeter.').","commonSituations":"User typed a full gRPC URL like '/package.Svc/Method' or 'package.Svc.Method' (three parts) in the task form instead of 'Svc.Method'; copy-paste with trailing dot; empty field because the workflow parameter substituted to blank.","solutions":["Use exactly 'ServiceName.RpcName' (one separator, both parts non-empty), e.g. 'Greeter.SayHello'.","Strip package prefixes and URL decorations: '/package.Greeter/SayHello' → 'Greeter.SayHello'.","Trim whitespace and verify the task-form field is not empty or parameter-substituted to blank.","If the proto uses nested services, use only the service's simple name; the descriptor lookup uses findServiceByName on the simple name."],"exampleFix":"// before\nnew GrpcDynamicService.MethodName(\"/example.Greeter/SayHello\"); // invalid\n// after\nnew GrpcDynamicService.MethodName(\"Greeter.SayHello\"); // ServiceName.RpcName","handlingStrategy":"validation","validationCode":"// Validate before constructing MethodName\nboolean isValidMethodName(String s) {\n    if (s == null) return false;\n    String[] p = s.split(\"\\\\.\");\n    return p.length == 2 && !p[0].isEmpty() && !p[1].isEmpty();\n}","typeGuard":null,"tryCatchPattern":"try {\n    service.call(\"Greeter.SayHello\", json, 5000);\n} catch (GrpcParserException e) {\n    if (e.getMessage().contains(\"method name is invalid\")) {\n        log.error(\"Use ServiceName.RpcName format, e.g. Greeter.SayHello, got: {}\", userInput);\n    }\n}","preventionTips":["Always format as ServiceName.RpcName with a single dot separator","Strip '/package.Svc/Method' URL-style names down to 'Svc.Method'","Trim user input and guard against blank values from parameter substitution","List available services/methods from the descriptor and use a dropdown instead of free text where possible"],"tags":["grpc","validation","identifier-format"],"backgroundTag":"invalid-identifier-format","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}