{"record":{"id":"af9dabf274948599","repo":"apache/hadoop","slug":"null-protocol","errorCode":null,"errorMessage":"Null protocol","messagePattern":"Null protocol","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/RPC.java","lineNumber":177,"sourceCode":"    if (protocol == null) {\n      return null;\n    }\n    ProtocolInfo anno = protocol.getAnnotation(ProtocolInfo.class);\n    return  (anno == null) ? protocol.getName() : anno.protocolName();\n  }\n  \n  /**\n   * Get the protocol version from protocol class.\n   * If the protocol class has a ProtocolAnnotation,\n   * then get the protocol version from the annotation;\n   * otherwise get it from the versionID field of the protocol class.\n   *\n   * @param protocol input protocol.\n   * @return ProtocolVersion.\n   */\n  static public long getProtocolVersion(Class<?> protocol) {\n    if (protocol == null) {\n      throw new IllegalArgumentException(\"Null protocol\");\n    }\n    long version;\n    ProtocolInfo anno = protocol.getAnnotation(ProtocolInfo.class);\n    if (anno != null) {\n      version = anno.protocolVersion();\n      if (version != -1)\n        return version;\n    }\n    try {\n      Field versionField = protocol.getField(\"versionID\");\n      versionField.setAccessible(true);\n      return versionField.getLong(protocol);\n    } catch (NoSuchFieldException ex) {\n      throw new RuntimeException(ex);\n    } catch (IllegalAccessException ex) {\n      throw new RuntimeException(ex);\n    }\n  }","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/RPC.java#L159-L195","documentation":"RPC.getProtocolVersion(Class<?> protocol) resolves a protocol's version, first from its @ProtocolInfo annotation (if protocolVersion != -1), then from a public static long versionID field. A null protocol class has no version to read, so it fails fast with IllegalArgumentException('Null protocol'). It is a caller-side wiring bug — the protocol variable was never assigned, typically in proxy construction paths (ProtocolProxy, RpcEngine version checks).","triggerScenarios":"Calling RPC.getProtocolVersion(null); passing a null protocolClass into RPC.getProxy/waitForProxy paths that forward it here; configuration-driven protocol loading where the class name resolves to null (Class.forName wrapped so failures yield null); generics erasure returning null from a map of protocols.","commonSituations":"Custom RPC clients building proxies from config keys that are missing or misspelled; UGI/doAs wrappers losing the protocol argument; test code passing an unset field.","solutions":["Null-check the protocol class before building proxies and fail with a message naming the config/source of the class.","Fix the upstream lookup: verify the protocol class name string, use Class.forName with error propagation instead of null-swallowing helpers.","Ensure the class also carries @ProtocolInfo(protocolVersion=...) or a versionID field, or the next step will fail differently."],"exampleFix":"// before\nClass<?> proto = protocolClasses.get(conf.get(\"my.rpc.protocol\")); // missing key -> null\nlong v = RPC.getProtocolVersion(proto); // IllegalArgumentException: Null protocol\n\n// after\nString name = Objects.requireNonNull(conf.get(\"my.rpc.protocol\"), \"my.rpc.protocol unset\");\nClass<?> proto;\ntry {\n proto = Class.forName(name);\n} catch (ClassNotFoundException e) {\n throw new IllegalStateException(\"Bad my.rpc.protocol: \" + name, e);\n}\nlong v = RPC.getProtocolVersion(proto);","handlingStrategy":"validation","validationCode":"java.util.Objects.requireNonNull(protocol,\n    \"protocol class must not be null when resolving its version\");\n// and ensure it is versioned\nif (protocol.getAnnotation(ProtocolInfo.class) == null\n    && !hasVersionIdField(protocol)) {\n  throw new IllegalStateException(protocol + \" needs @ProtocolInfo or versionID\");\n}","typeGuard":"static boolean isVersionedProtocol(Class<?> c) {\n  if (c == null) return false;\n  ProtocolInfo anno = c.getAnnotation(ProtocolInfo.class);\n  if (anno != null && anno.protocolVersion() != -1) return true;\n  try { c.getField(\"versionID\"); return true; }\n  catch (NoSuchFieldException e) { return false; }\n}","tryCatchPattern":null,"preventionTips":["Resolve protocol classes eagerly with Class.forName and fail loudly; never let null flow into RPC APIs.","Validate config-driven class names at startup with a clear error naming the key.","Give every custom protocol @ProtocolInfo(protocolVersion=...) or a versionID field."],"tags":["hadoop","ipc","rpc","null-argument","protocol","validation"],"backgroundTag":"null-argument-rejected","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}