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
- In tests, create protocol mocks with MockitoUtil.mockProtocol(MyProtocol.class) — it installs a closeable invocation handler so RPC.stopProxy works.
- Only pass objects obtained from RPC.getProxy, RPC.waitForProxy, or RPC.getProtocolProxy to RPC.stopProxy.
- If you hold the implementation rather than a proxy, close it via its own lifecycle method, never via RPC.stopProxy.
- 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
- Create protocol mocks with MockitoUtil.mockProtocol, never Mockito.mock, when tests will call RPC.stopProxy.
- Keep the exact object returned by RPC.getProxy for later cleanup — do not substitute lookalikes.
- In generic cleanup utilities, skip objects failing the stoppable-proxy check instead of calling stopProxy unconditionally.
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
- Cannot close proxy since it is null
- Failed to get connection for {}, {}: {} is already stopped
- key + ": Stream is closed!"
- Stream closed
- Stream is closed!
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/d209a090db891f67.
Report an issue: GitHub.