apache/hadoop · error · HadoopIllegalArgumentException

Cannot close proxy - is not Closeable or does not provide cl

Error message

Cannot close proxy - is not Closeable or does not provide closeable invocation handler ${proxyClass}

What it means

RPC.stopProxy throws HadoopIllegalArgumentException when the argument is neither Closeable nor a dynamic proxy whose InvocationHandler is Closeable — i.e., not an object the RPC layer created. The source comment names the classic cause: Mockito mocks of a protocol in unit tests, which must instead be built with MockitoUtil.mockProtocol(). It can also fire when the exception path of stopProxy (IOException/IllegalArgumentException from the close attempt) falls through to the final throw.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/RPC.java:820

        ((Closeable) proxy).close();
        return;
      } else {
        InvocationHandler handler = Proxy.getInvocationHandler(proxy);
        if (handler instanceof Closeable) {
          ((Closeable) handler).close();
          return;
        }
      }
    } catch (IOException e) {
      LOG.error("Closing proxy or invocation handler caused exception", e);
    } catch (IllegalArgumentException e) {
      LOG.error("RPC.stopProxy called on non proxy: class=" + proxy.getClass().getName(), e);
    }
    
    // If you see this error on a mock object in a unit test you're
    // developing, make sure to use MockitoUtil.mockProtocol() to
    // create your mock.
    throw new HadoopIllegalArgumentException(
        "Cannot close proxy - is not Closeable or "
            + "does not provide closeable invocation handler "
            + proxy.getClass());
  }
  /**
   * Get the RPC time from configuration;
   * If not set in the configuration, return the default value.
   *
   * @param conf Configuration
   * @return the RPC timeout (ms)
   */
  public static int getRpcTimeout(Configuration conf) {
    return conf.getInt(CommonConfigurationKeys.IPC_CLIENT_RPC_TIMEOUT_KEY,
        CommonConfigurationKeys.IPC_CLIENT_RPC_TIMEOUT_DEFAULT);
  }

  /**
   * Class to construct instances of RPC server with specific options.

View on GitHub (pinned to 2add963021)

Solutions

  1. In tests, create protocol mocks with MockitoUtil.mockProtocol(MyProtocol.class) — it installs a closeable invocation handler so RPC.stopProxy works.
  2. Only pass objects obtained from RPC.getProxy, RPC.waitForProxy, or RPC.getProtocolProxy to RPC.stopProxy.
  3. If you hold the implementation rather than a proxy, close it via its own lifecycle method, never via RPC.stopProxy.
  4. In generic cleanup code, guard first: skip objects that are not Closeable and whose invocation handler is not Closeable.

Example fix

// before
ClientProtocol nn = Mockito.mock(ClientProtocol.class);
// ... test body ...
RPC.stopProxy(nn); // HadoopIllegalArgumentException
// after
ClientProtocol nn = MockitoUtil.mockProtocol(ClientProtocol.class);
// ... test body ...
RPC.stopProxy(nn); // closeable handler installed, no throw
Defensive patterns

Strategy: type-guard

Type guard

static boolean isStoppableProxy(Object o) {
  if (o == null || !Proxy.isProxyClass(o.getClass())) {
    return false;
  }
  if (o instanceof Closeable) {
    return true;
  }
  return Proxy.getInvocationHandler(o) instanceof Closeable;
}

Prevention

When it happens

Trigger: Passing a Mockito mock created with Mockito.mock(MyProtocol.class) to RPC.stopProxy; passing a plain protocol implementation instance instead of the proxy object returned by RPC.getProxy/getProtocolProxy/waitForProxy; passing a non-proxy object on which Proxy.getInvocationHandler throws IllegalArgumentException and falls through to this error.

Common situations: Unit tests of client code closing mocked protocols (HBase/HDFS client tests); code confusing the server-side service instance with the client-side proxy; generic cleanup utilities calling RPC.stopProxy on arbitrary objects.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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