{"record":{"id":"f27729f88b0dbe51","repo":"aeron-io/aeron","slug":"aeron-client-must-use-conductor-agent-invoker","errorCode":null,"errorMessage":"Aeron client must use conductor agent invoker","messagePattern":"Aeron client must use conductor agent invoker","errorType":"validation","errorClass":"ClusterException","httpStatus":null,"severity":"error","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/ClusterBackup.java","lineNumber":794,"sourceCode":"                    errorCounter = ClusterCounters.allocateVersioned(\n                        aeron,\n                        buffer,\n                        \"ClusterBackup Errors\",\n                        CLUSTER_BACKUP_ERROR_COUNT_TYPE_ID,\n                        clusterId,\n                        ClusterBackupVersion.VERSION,\n                        ClusterBackupVersion.GIT_SHA);\n                }\n            }\n\n            if (!(aeron.context().subscriberErrorHandler() instanceof RethrowingErrorHandler))\n            {\n                throw new ClusterException(\"Aeron client must use a RethrowingErrorHandler\");\n            }\n\n            if (!aeron.context().useConductorAgentInvoker())\n            {\n                throw new ClusterException(\"Aeron client must use conductor agent invoker\");\n            }\n\n            if (null == errorCounter)\n            {\n                throw new ClusterException(\"error counter must be supplied if aeron client is\");\n            }\n\n            if (null == countedErrorHandler)\n            {\n                countedErrorHandler = new CountedErrorHandler(errorHandler, errorCounter);\n                if (ownsAeronClient)\n                {\n                    aeron.context().errorHandler(countedErrorHandler);\n                }\n            }\n\n            if (null == stateCounter)\n            {","sourceCodeStart":776,"sourceCodeEnd":812,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/ClusterBackup.java#L776-L812","documentation":"ClusterBackup must interact with the Aeron client via the conductor agent invoker so client conductor work runs on the backup agent's thread rather than a separate client conductor thread. conclude() throws this ClusterException when the supplied Aeron context does not enable useConductorAgentInvoker().","triggerScenarios":"Concluding a ClusterBackup.Context with an Aeron client created from a context where aeron.context().useConductorAgentInvoker() is false (the default is a dedicated client conductor thread).","commonSituations":"Reusing a shared Aeron client built for normal (threaded) usage; forgetting clientContext.useConductorAgentInvoker(true) when setting up a dedicated client for the backup agent.","solutions":["Create the Aeron client with context.useConductorAgentInvoker(true) and drive it via aeron.conductorAgentInvoker() inside the backup agent.","Use a dedicated Aeron client for ClusterBackup instead of reusing an application client with a conductor thread.","Review Aeron cluster samples (ClusterBackup) for the canonical client setup."],"exampleFix":"// before\nAeron aeron = Aeron.connect(new Aeron.Context());\n// after\nAeron aeron = Aeron.connect(new Aeron.Context().useConductorAgentInvoker(true));","handlingStrategy":"validation","validationCode":"if (!aeronCtx.useConductorAgentInvoker()) { throw new IllegalStateException(\"backup requires conductor agent invoker\"); }","typeGuard":"static boolean usesAgentInvoker(Aeron.Context c) { return c.useConductorAgentInvoker(); }","tryCatchPattern":"try {\n    ctx.conclude();\n} catch (ClusterException e) {\n    if (e.getMessage().contains(\"conductor agent invoker\")) { log.error(\"call Aeron.Context.useConductorAgentInvoker(true)\"); }\n    throw e;\n}","preventionTips":["Always enable useConductorAgentInvoker(true) on the client used by ClusterBackup","Drive the client with aeron.conductorAgentInvoker() from the backup agent thread","Copy the canonical setup from Aeron's ClusterBackup samples"],"tags":["configuration","agent-invoker","aeron-client","threading"],"backgroundTag":"conflicting-config-options","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}