{"record":{"id":"77b638dc466a2169","repo":"apache/hadoop","slug":"too-many-or-few-parameters-for-request-method-77b638","errorCode":null,"errorMessage":"Too many or few parameters for request. Method: [{}], Expected: 2, Actual: {}","messagePattern":"Too many or few parameters for request\\. Method: \\[(.+?)\\], Expected: 2, Actual: (.+?)","errorType":"validation","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/ProtobufRpcEngine2.java","lineNumber":230,"sourceCode":"     * <li>Exceptions from the server are wrapped in RemoteException and are\n     * set as cause in ServiceException</li>\n     * </ol>\n     *\n     * Note that the client calling protobuf RPC methods, must handle\n     * ServiceException by getting the cause from the ServiceException. If the\n     * cause is RemoteException, then unwrap it to get the exception thrown by\n     * the server.\n     */\n    @Override\n    public Message invoke(Object proxy, final Method method, Object[] args)\n        throws ServiceException {\n      long startTime = 0;\n      if (LOG.isDebugEnabled()) {\n        startTime = Time.monotonicNow();\n      }\n\n      if (args.length != 2) { // RpcController + Message\n        throw new ServiceException(\n            \"Too many or few parameters for request. Method: [\"\n            + method.getName() + \"]\" + \", Expected: 2, Actual: \"\n            + args.length);\n      }\n      if (args[1] == null) {\n        throw new ServiceException(\"null param while calling Method: [\"\n            + method.getName() + \"]\");\n      }\n\n      // if Tracing is on then start a new span for this rpc.\n      // guard it in the if statement to make sure there isn't\n      // any extra string manipulation.\n      Tracer tracer = Tracer.curThreadTracer();\n      TraceScope traceScope = null;\n      if (tracer != null) {\n        traceScope = tracer.newScope(RpcClientUtil.methodToTraceString(method));\n      }\n","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/ProtobufRpcEngine2.java#L212-L248","documentation":"ProtobufRpcEngine2 (the protobuf-v2/default engine in newer Hadoop) has the identical client-side InvocationHandler contract: every method invoked through the proxy must take exactly (RpcController, Message). args.length != 2 throws ServiceException before any network activity. It indicates a non-RPC method was routed through the engine-2 proxy.","triggerScenarios":"Adding convenience/default methods with other arities to a protocolPB interface and calling them on the proxy; reflective invocation that reshapes the argument array; using the PB proxy where the translator should be used.","commonSituations":"Custom protocols migrating to ProtobufRpcEngine2 (proto3); library upgrades where interfaces gained default helper methods; generic proxy wrappers (caching, metrics) that call toString/equals-like extras reflectively.","solutions":["Restrict the PB protocol interface to 2-arg (RpcController, Message) methods; move helpers to translators or separate interfaces.","Call default/interface helper methods on a typed reference, not through the RPC proxy.","Guard reflective invocations with a signature check (parameter count == 2)."],"exampleFix":"// before\npublic interface StoreProtocolPB {\n  StoreResponseProto put(RpcController c, StoreRequestProto req);\n  void close(); // 0-arg helper -> ServiceException when invoked via proxy\n}\nproxy.close();\n\n// after\npublic interface StoreProtocolPB {\n  StoreResponseProto put(RpcController c, StoreRequestProto req);\n}\n// close() moved to the translator class that owns the proxy lifecycle","handlingStrategy":"validation","validationCode":"for (Method m : protoInterface.getMethods()) {\n  if (m.getParameterCount() != 2) {\n    throw new IllegalStateException(\"ProtobufRpcEngine2 requires exactly 2-arg methods, found: \" + m);\n  }\n}","typeGuard":"static boolean isProtobufRpcMethod(Method m) {\n  Class<?>[] p = m.getParameterTypes();\n  return p.length == 2\n      && RpcController.class.isAssignableFrom(p[0])\n      && com.google.protobuf.Message.class.isAssignableFrom(p[1]);\n}","tryCatchPattern":null,"preventionTips":["Keep engine-2 PB interfaces strictly (RpcController, Message)-shaped; helpers belong in translators.","Add an ArchUnit/reflection test forbidding extra methods on protocolPB interfaces.","Beware reflective wrappers adding Object methods or defaults to proxies."],"tags":["hadoop","ipc","rpc","protobuf","proxy","reflection","protobuf-rpc-engine2"],"backgroundTag":"rpc-method-signature-mismatch","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}