aeron-io/aeron · error · ClusterException

Aeron client must use a RethrowingErrorHandler

Error message

Aeron client must use a RethrowingErrorHandler

What it means

ClusterBackup drives its media driver interactions from within an agent and requires the Aeron client's subscriber error handler to be a RethrowingErrorHandler, so client errors propagate to the backup agent instead of being swallowed by a default logging handler. conclude() throws this ClusterException when a custom (non-rethrowing) error handler is configured on the Aeron context.

Solutions

  1. Use RethrowingErrorHandler.INSTANCE as the subscriber error handler on the Aeron.Context used by the backup.
  2. Create a dedicated Aeron client for the ClusterBackup rather than reusing one configured for the application.
  3. Move custom error logging to a wrapper that still rethrows, or handle errors via the supplied errorCounter/AgentListener instead.

Example fix

// before
Aeron.Context aeronCtx = new Aeron.Context().subscriberErrorHandler(myLoggingHandler);
// after
Aeron.Context aeronCtx = new Aeron.Context().subscriberErrorHandler(RethrowingErrorHandler.INSTANCE);
Defensive patterns

Strategy: validation

Validate before calling

if (!(aeronCtx.subscriberErrorHandler() instanceof RethrowingErrorHandler)) { throw new IllegalStateException("backup requires RethrowingErrorHandler"); }

Type guard

static boolean usesRethrowingHandler(Aeron.Context c) { return c.subscriberErrorHandler() instanceof RethrowingErrorHandler; }

Try / catch

try {
    ctx.conclude();
} catch (ClusterException e) {
    if (e.getMessage().contains("RethrowingErrorHandler")) { log.error("configure Aeron.Context with RethrowingErrorHandler.INSTANCE"); }
    throw e;
}

Prevention

When it happens

Trigger: Concluding a ClusterBackup.Context after supplying an Aeron instance whose context error handler was replaced (aeron.context().subscriberErrorHandler(customHandler)) with anything other than RethrowingErrorHandler.INSTANCE.

Common situations: Sharing an application-wide Aeron client configured with a logging error handler; copying driver/client setup code that sets a custom ErrorHandler; embedding ClusterBackup in an app with centralized error swallowing.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/34d5d15b5ee2ea0c. Report an issue: GitHub.

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ClusterBackup.java:789

                        .clientLock(NoOpLock.INSTANCE)
                        .clientName(clientName));

                if (null == errorCounter)
                {
                    errorCounter = ClusterCounters.allocateVersioned(
                        aeron,
                        buffer,
                        "ClusterBackup Errors",
                        CLUSTER_BACKUP_ERROR_COUNT_TYPE_ID,
                        clusterId,
                        ClusterBackupVersion.VERSION,
                        ClusterBackupVersion.GIT_SHA);
                }
            }

            if (!(aeron.context().subscriberErrorHandler() instanceof RethrowingErrorHandler))
            {
                throw new ClusterException("Aeron client must use a RethrowingErrorHandler");
            }

            if (!aeron.context().useConductorAgentInvoker())
            {
                throw new ClusterException("Aeron client must use conductor agent invoker");
            }

            if (null == errorCounter)
            {
                throw new ClusterException("error counter must be supplied if aeron client is");
            }

            if (null == countedErrorHandler)
            {
                countedErrorHandler = new CountedErrorHandler(errorHandler, errorCounter);
                if (ownsAeronClient)
                {
                    aeron.context().errorHandler(countedErrorHandler);

View on GitHub (pinned to 6d60124e15)