apache/hadoop · error · IllegalArgumentException

ReRegistration of rpcKind: ${rpcKind}

Error message

ReRegistration of rpcKind: ${rpcKind}

What it means

Server.registerProtocolEngine maps an RPC.RpcKind to a request-wrapper class plus RpcInvoker in a static map; registering a kind that already has an entry throws IllegalArgumentException and puts the original mapping back. The framework registers its built-in kinds (RPC_BUILTIN, RPC_WRITABLE, RPC_PROTOCOL_BUFFER) once, so this error always means custom code re-registered an existing kind.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java:297

  /**
   * Register a RPC kind and the class to deserialize the rpc request.
   * 
   * Called by static initializers of rpcKind Engines
   * @param rpcKind - input rpcKind.
   * @param rpcRequestWrapperClass - this class is used to deserialze the
   *  the rpc request.
   * @param rpcInvoker - use to process the calls on SS.
   */
  
  public static void registerProtocolEngine(RPC.RpcKind rpcKind, 
          Class<? extends Writable> rpcRequestWrapperClass,
          RpcInvoker rpcInvoker) {
    RpcKindMapValue  old = 
        rpcKindMap.put(rpcKind, new RpcKindMapValue(rpcRequestWrapperClass, rpcInvoker));
    if (old != null) {
      rpcKindMap.put(rpcKind, old);
      throw new IllegalArgumentException("ReRegistration of rpcKind: " +
          rpcKind);      
    }
    LOG.debug("rpcKind={}, rpcRequestWrapperClass={}, rpcInvoker={}.",
        rpcKind, rpcRequestWrapperClass, rpcInvoker);
  }
  
  public Class<? extends Writable> getRpcRequestWrapper(
      RpcKindProto rpcKind) {
    if (rpcRequestClass != null)
       return rpcRequestClass;
    RpcKindMapValue val = rpcKindMap.get(ProtoUtil.convert(rpcKind));
    return (val == null) ? null : val.rpcRequestWrapperClass; 
  }

  protected RpcInvoker getServerRpcInvoker(RPC.RpcKind rpcKind) {
    return getRpcInvoker(rpcKind);
  }

View on GitHub (pinned to 2add963021)

Solutions

  1. Register each RpcKind exactly once per JVM — guard with a static AtomicBoolean/set so repeated init calls are no-ops.
  2. Never re-register the built-in kinds; pick a genuinely distinct RPC.RpcKind for a custom engine.
  3. In tests, register once for the whole suite (@BeforeClass or static block) rather than per test method.

Example fix

// before
public void init() {
  Server.registerProtocolEngine(MY_KIND, MyWrapper.class, myInvoker); // 2nd call throws
}
// after
private static final AtomicBoolean REGISTERED = new AtomicBoolean(false);
public void init() {
  if (REGISTERED.compareAndSet(false, true)) {
    Server.registerProtocolEngine(MY_KIND, MyWrapper.class, myInvoker);
  }
}
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<RPC.RpcKind> REGISTERED_BY_ME =
    ConcurrentHashMap.newKeySet();

if (REGISTERED_BY_ME.add(rpcKind)) {
  Server.registerProtocolEngine(rpcKind, wrapperClass, invoker);
}

Prevention

When it happens

Trigger: Custom RPC engines calling registerProtocolEngine for an RpcKind already registered — including the built-in RPC_PROTOCOL_BUFFER; registration inside per-instance init or per-test setup that runs twice; static initializers re-executed via class reloading in embedded/OSGi-like containers.

Common situations: Third-party protocol-engine integrations; unit tests that construct many servers and register the engine in each setup without a guard; a plugin and service init both registering the same custom kind.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/61e16e58ed89c415. Report an issue: GitHub.