aeron-io/aeron · error · ClusterException
Aeron client must use a RethrowingErrorHandler
Error message
Aeron client must use a RethrowingErrorHandler
What it means
Thrown as ClusterException when the Aeron client used by the ClusteredServiceContainer has a subscriberErrorHandler that is not a RethrowingErrorHandler. The clustered service relies on exceptions from subscriber error handlers propagating up so log failures abort the container instead of being silently swallowed, which would corrupt cluster consistency.
Solutions
- Set aeron.context().subscriberErrorHandler(new RethrowingErrorHandler()) on the client context passed to the container
- Let the container create its own Aeron client (do not override the error handler) if you don't need custom handling
- Wrap custom handling around RethrowingErrorHandler by subclassing and rethrowing after logging
- If Aeron.Context defaults were changed, restore the default rethrowing subscriber error handler
Example fix
// before
Aeron.Context aeronCtx = new Aeron.Context()
.subscriberErrorHandler(new LoggingErrorHandler());
aeron = Aeron.connect(aeronCtx);
// after
Aeron.Context aeronCtx = new Aeron.Context()
.subscriberErrorHandler(new RethrowingErrorHandler());
aeron = Aeron.connect(aeronCtx); Defensive patterns
Strategy: validation
Validate before calling
if (!(aeronCtx.subscriberErrorHandler() instanceof RethrowingErrorHandler)) {
aeronCtx.subscriberErrorHandler(new RethrowingErrorHandler());
} Type guard
boolean isRethrowing(Aeron.Context ctx) { return ctx.subscriberErrorHandler() instanceof RethrowingErrorHandler; } Prevention
- Never replace the subscriber error handler on Aeron contexts used by clustered services
- Subclass RethrowingErrorHandler if custom logging is needed, and always rethrow
- Audit shared/global Aeron context configuration before embedding the container
When it happens
Trigger: Creating the Aeron client with Aeron.connect(ctx) where ctx.subscriberErrorHandler(...) is set to a custom (non-rethrowing) handler, or a default handler that only logs; building the Aeron client inside the container with a pre-configured context carrying the wrong error handler; letting the container create its own client (ownsAeronClient) after overriding the handler.
Common situations: Embedding the container in an application that globally configures Aeron contexts with logging error handlers; copy-pasted driver/client context reuse; replacing RethrowingErrorHandler to suppress image errors without realizing the cluster requires rethrow semantics.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Aeron client must use a RethrowingErrorHandler
- not found in
- clusterMembers and endpoints differ
- either a instance or class name for the service must be…
- service id outside allowed range
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/04776cbe9253383e.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/service/ClusteredServiceContainer.java:949
}
if (null == aeron)
{
aeron = Aeron.connect(
new Aeron.Context()
.aeronDirectoryName(aeronDirectoryName)
.errorHandler(errorHandler)
.subscriberErrorHandler(RethrowingErrorHandler.INSTANCE)
.awaitingIdleStrategy(YieldingIdleStrategy.INSTANCE)
.epochClock(epochClock)
.clientName(serviceName));
ownsAeronClient = true;
}
if (!(aeron.context().subscriberErrorHandler() instanceof RethrowingErrorHandler))
{
throw new ClusterException("Aeron client must use a RethrowingErrorHandler");
}
final ExpandableArrayBuffer tempBuffer = new ExpandableArrayBuffer();
if (null == errorCounter)
{
errorCounter = ClusterCounters.allocateServiceErrorCounter(aeron, tempBuffer, clusterId, serviceId);
}
if (null == countedErrorHandler)
{
countedErrorHandler = new CountedErrorHandler(errorHandler, errorCounter);
if (ownsAeronClient)
{
aeron.context().errorHandler(countedErrorHandler);
}
}
if (null == dutyCycleTracker)View on GitHub (pinned to 6d60124e15)