apache/cassandra · error · java.lang.IllegalArgumentException
MBeanServer already initialized
Error message
MBeanServer already initialized
What it means
The proxy stores its single MBeanServer reference in the field mbs and treats it as write-once. A second setMBeanServer call after initialization throws IllegalArgumentException("MBeanServer already initialized") at line 187. This protects against hot-swapping the server out from under live connections and cached authorization state.
Source
Thrown at src/java/org/apache/cassandra/auth/jmx/AuthorizationProxy.java:187
{
if ("getMBeanServer".equals(methodName))
throw new SecurityException("Access denied");
// Corresponds to MBeanServer.invoke
if (methodName.equals("invoke") && args.length == 4)
checkVulnerableMethods(args);
// Allow setMBeanServer iff performed on behalf of the connector server itself
if (("setMBeanServer").equals(methodName))
{
if (subject != null)
throw new SecurityException("Access denied");
if (args[0] == null)
throw new IllegalArgumentException("Null MBeanServer");
if (mbs != null)
throw new IllegalArgumentException("MBeanServer already initialized");
mbs = (MBeanServer) args[0];
return null;
}
if (authorize(subject, methodName, args))
{
Object invoke = invoke(method, args);
listener.onInvocation(subject, method, args);
return invoke;
}
throw new SecurityException("Access Denied");
}
catch (Exception e)
{
listener.onFailure(subject, method, args, e);
throw e;View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Do not call setMBeanServer more than once per proxy; construct a fresh AuthorizationProxy for each new connector server.
- If re-initializing in tests, build a new proxy instance (or reset mbs via the test-visible setter) before calling setMBeanServer again.
- Reuse the already-initialized MBeanServer instead of trying to replace it.
Example fix
// before AuthorizationProxy proxy = new AuthorizationProxy(...); // created earlier and already set proxy.setMBeanServer(newServer); // IllegalStateException/IAX: already initialized // after AuthorizationProxy proxy = new AuthorizationProxy(); // fresh instance per connector proxy.setMBeanServer(newServer);
Defensive patterns
Strategy: validation
Validate before calling
// guard at the call site: setMBeanServer is write-once per proxy
if (proxyAlreadyInitialized)
throw new IllegalStateException("Create a new AuthorizationProxy instead of re-initializing the existing one"); Try / catch
try {
proxy.setMBeanServer(server);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("already initialized")) {
logger.info("MBeanServer already set; reusing existing instance");
} else throw e;
} Prevention
- Create a fresh AuthorizationProxy per JMXConnectorServer lifecycle.
- In test suites, recreate proxy instances between Cassandra bootstrap cycles rather than reusing them.
- Treat the proxy's mbs field as write-once; never design code paths that replace the server at runtime.
When it happens
Trigger: setMBeanServer called with subject == null and a non-null server, while AuthorizationProxy.mbs has already been set by an earlier setMBeanServer during connector startup.
Common situations: Creating a second JMXConnectorServer that reuses the same proxy; restarting the connector within the same JVM without recreating the proxy; test suites that bootstrap Cassandra's JMX setup multiple times in one JVM.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Unable to stop gossip because the node is not in the normal
- No configured daemon
- %s is not a valid JMX resource name
- SASL negotiation not complete
- JAAS login configuration missing for JMX authenticator setup
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/a9a5d0774e69941e.
Report an issue: GitHub.