{"record":{"id":"c1007ba123dcac62","repo":"flowable/flowable-engine","slug":"jmx-connection-already-exists","errorCode":null,"errorMessage":"JMX connection:{} already exists.","messagePattern":"JMX connection:(.+?) already exists\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"modules/flowable-jmx/src/main/java/org/flowable/management/jmx/DefaultManagementAgent.java","lineNumber":233,"sourceCode":"            url = new JMXServiceURL(\"service:jmx:rmi:///jndi/rmi://\" + host + \":\" + registryPort + path);\r\n        }\r\n\r\n        cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);\r\n\r\n        // use async thread for starting the JMX Connector\r\n        // (no need to use a thread pool or enlist in JMX as this thread is\r\n        // terminated when the JMX connector has been started)\r\n        Thread thread = new Thread(new Runnable() {\r\n\r\n            @Override\r\n            public void run() {\r\n                try {\r\n                    LOGGER.debug(\"Staring JMX Connector thread to listen at: {}\", url);\r\n                    cs.start();\r\n                    LOGGER.info(\"JMX Connector thread started and listening at: {}\", url);\r\n                } catch (IOException ioe) {\r\n                    if (ioe.getCause() instanceof javax.naming.NameAlreadyBoundException) {\r\n                        LOGGER.warn(\"JMX connection:{} already exists.\", url);\r\n                    } else {\r\n                        LOGGER.warn(\"Could not start JMXConnector thread at: {}. JMX Connector not in use.\", url, ioe);\r\n                    }\r\n                }\r\n            }\r\n        }, \"jmxConnectorStarterThread\");\r\n        thread.start();\r\n    }\r\n\r\n}\r\n","sourceCodeStart":215,"sourceCodeEnd":244,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-jmx/src/main/java/org/flowable/management/jmx/DefaultManagementAgent.java#L215-L244","documentation":"When the JMX connector server thread starts the connector (cs.start()), an IOException whose cause is javax.naming.NameAlreadyBoundException means another JMX connector is already bound at the same JNDI/RMI URL. DefaultManagementAgent logs this as a warning and does not retry, treating the existing binding as usable. It usually indicates the previous connector was not unbound (e.g. after an unclean shutdown or double agent initialization).","triggerScenarios":"The jmxConnectorStarterThread calls JMXConnectorServer.start() and the underlying bind to the RMI registry/JNDI name fails because a binding with the same service URL already exists — e.g. the agent's createJmxConnector being run twice, or a previous JVM/connector crashed without cleanup.","commonSituations":"Hot redeploy of the engine in the same JVM without stopping the old connector; two engine instances in one JVM both enabling JMX on the same port/path; container restart where the RMI registry lives outside the JVM and retains stale bindings.","solutions":["Ensure DefaultManagementAgent is initialized only once per JVM (guard agent startup, e.g. check existing MBean server/connector before creating).","Use a unique registry/connector port and serviceUrlPath per engine instance when running multiple engines in one JVM.","Stop and unbind the previous connector (cs.stop()) on shutdown so the binding is released; the warning is usually benign and the existing connector can be used as-is.","If a stale external RMI registry holds the binding, restart or clear the registry."],"exampleFix":"// before\n// two engines, same config\nflowable.jmx.registryPort=1099\nflowable.jmx.serviceUrlPath=/jmxrmi\n// after\n// engine A\nflowable.jmx.registryPort=1099\nflowable.jmx.serviceUrlPath=/jmxrmi-engineA\n// engine B\nflowable.jmx.registryPort=1100\nflowable.jmx.serviceUrlPath=/jmxrmi-engineB","handlingStrategy":"fallback","validationCode":"// Before starting a second engine in the same JVM, ensure unique JMX endpoints\nassert engineAJmxPort != engineBJmxPort : \"each engine needs its own JMX registry/connector port\";","typeGuard":null,"tryCatchPattern":"try {\n    connectorServer.start();\n} catch (IOException ioe) {\n    if (ioe.getCause() instanceof javax.naming.NameAlreadyBoundException) {\n        // existing binding: treat as already-managed, do not fail startup\n        log.warn(\"JMX connector already bound at {}\", url);\n    } else {\n        throw ioe;\n    }\n}","preventionTips":["Initialize DefaultManagementAgent only once per JVM","Register a shutdown hook that calls connectorServer.stop() to unbind cleanly","Give each engine instance unique ports and serviceUrlPath values"],"tags":["jmx","rmi","name-already-bound","startup"],"backgroundTag":"address-already-in-use","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}