aeron-io/aeron · error · ConcurrentConcludeException
ConcurrentConcludeException
Error message
ConcurrentConcludeException
What it means
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.
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.
Example fix
// before ctx.conclude(); clusterBackup = new ClusterBackup(ctx); ctx.conclude(); // second call -> throws // after ctx.conclude(); // only once clusterBackup = new ClusterBackup(ctx);
Defensive patterns
Strategy: type-guard
Validate before calling
if (!concluded) { ctx.conclude(); concluded = true; } Type guard
static boolean isConcluded(ClusterBackup.Context ctx) { return ctx != null && ctx.isConcluded(); } // guard via public flag if exposed Try / catch
try {
ctx.conclude();
backup = new ClusterBackup(ctx);
} catch (ConcurrentConcludeException e) {
throw new IllegalStateException("ClusterBackup context concluded more than once", e);
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
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
- ConcurrentConcludeException
- Concurrent conclude of ConsensusModule.Context not permitted
- counter is closed
- publication is closed
- unexpected Aeron close
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/ccd5cdf282bcb8e6.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ClusterBackup.java:685
return (Context)super.clone();
}
catch (final CloneNotSupportedException ex)
{
throw new RuntimeException(ex);
}
}
/**
* Conclude configuration by setting up defaults when specifics are not provided.
*/
@SuppressWarnings("MethodLength")
public void conclude()
{
final ExpandableArrayBuffer buffer = new ExpandableArrayBuffer();
if ((boolean)IS_CONCLUDED_VH.getAndSet(this, true))
{
throw new ConcurrentConcludeException();
}
if (null == clusterDir)
{
clusterDir = new File(clusterDirectoryName);
}
else
{
clusterDirectoryName = clusterDir.getPath();
}
if (deleteDirOnStart)
{
IoUtil.delete(clusterDir, false);
}
if (null == catchupEndpoint)
{View on GitHub (pinned to 6d60124e15)