{"record":{"id":"ccd5cdf282bcb8e6","repo":"aeron-io/aeron","slug":"concurrentconcludeexception-clusterbackup","errorCode":null,"errorMessage":"ConcurrentConcludeException","messagePattern":"ConcurrentConcludeException","errorType":"exception","errorClass":"ConcurrentConcludeException","httpStatus":null,"severity":"error","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/ClusterBackup.java","lineNumber":685,"sourceCode":"                return (Context)super.clone();\n            }\n            catch (final CloneNotSupportedException ex)\n            {\n                throw new RuntimeException(ex);\n            }\n        }\n\n        /**\n         * Conclude configuration by setting up defaults when specifics are not provided.\n         */\n        @SuppressWarnings(\"MethodLength\")\n        public void conclude()\n        {\n            final ExpandableArrayBuffer buffer = new ExpandableArrayBuffer();\n\n            if ((boolean)IS_CONCLUDED_VH.getAndSet(this, true))\n            {\n                throw new ConcurrentConcludeException();\n            }\n\n            if (null == clusterDir)\n            {\n                clusterDir = new File(clusterDirectoryName);\n            }\n            else\n            {\n                clusterDirectoryName = clusterDir.getPath();\n            }\n\n            if (deleteDirOnStart)\n            {\n                IoUtil.delete(clusterDir, false);\n            }\n\n            if (null == catchupEndpoint)\n            {","sourceCodeStart":667,"sourceCodeEnd":703,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/ClusterBackup.java#L667-L703","documentation":"ClusterBackup.Context.conclude() is guarded against being invoked more than once using an atomic IS_CONCLUDED flag. Calling conclude() (directly or indirectly via conclude/CloseHelper on the same Context) a second time throws ConcurrentConcludeException. Contexts must be concluded exactly once before starting the ClusterBackup.","triggerScenarios":"Calling ClusterBackup.Context.conclude() twice on the same Context instance, or concurrent conclusion from two threads (getAndSet wins in one thread and the other throws).","commonSituations":"Application code concluding the context and then also passing ownership to a helper that concludes it again; launching ClusterBackup from two threads with a shared Context.","solutions":["Conclude the Context exactly once, in the single thread that owns ClusterBackup startup.","If reusing a Context after a failed attempt, create a new Context instead of re-concluding the old one.","Guard concurrent startup with application-level synchronization or a boolean flag before calling conclude().","Use try-with-resources/ownership conventions: let ClusterBackup close its own context rather than concluding it manually."],"exampleFix":"// before\nctx.conclude();\nclusterBackup = new ClusterBackup(ctx);\nctx.conclude(); // second call -> throws\n// after\nctx.conclude(); // only once\nclusterBackup = new ClusterBackup(ctx);","handlingStrategy":"type-guard","validationCode":"if (!concluded) { ctx.conclude(); concluded = true; }","typeGuard":"static boolean isConcluded(ClusterBackup.Context ctx) { return ctx != null && ctx.isConcluded(); } // guard via public flag if exposed","tryCatchPattern":"try {\n    ctx.conclude();\n    backup = new ClusterBackup(ctx);\n} catch (ConcurrentConcludeException e) {\n    throw new IllegalStateException(\"ClusterBackup context concluded more than once\", e);\n}","preventionTips":["Conclude each Context exactly once, in one owner thread","Never share a Context across concurrent startup paths","Let ClusterBackup own/close the context instead of reusing it after close"],"tags":["lifecycle","concurrency","double-initialization","aeron-cluster"],"backgroundTag":"invalid-state-transition","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"}