aeron-io/aeron · error · ClusterException

failed to instantiate ClusterClock

Error message

failed to instantiate ClusterClock <clockClassName>

What it means

When no ClusterClock is set, conclude() instantiates one reflectively from the class named by the CLUSTER_CLOCK_PROP_NAME system property (default MillisecondClusterClock). If the class cannot be found, has no no-arg constructor, is not a ClusterClock, or its constructor throws, the exception is wrapped as a ClusterException "failed to instantiate ClusterClock <className>".

Solutions

  1. Fix the system property to a fully-qualified ClusterClock implementation with a public no-arg constructor
  2. Remove the property to fall back to MillisecondClusterClock
  3. Call ctx.clusterClock(new MillisecondClusterClock()) (or your implementation) explicitly instead of relying on reflection

Example fix

// before
System.setProperty("aeron.cluster.clock", "io.aeron.cluster.HighResClock"); // class missing
// after
System.setProperty("aeron.cluster.clock", "io.aeron.cluster.HighResolutionClusterClock");
// or better: ctx.clusterClock(new HighResolutionClusterClock());
Defensive patterns

Strategy: try-catch

Validate before calling

String name = System.getProperty("aeron.cluster.clock");
if (name != null) {
    Class<?> c = Class.forName(name);
    if (!ClusterClock.class.isAssignableFrom(c) || c.getConstructor().getModifiers() != Modifier.PUBLIC) {
        throw new IllegalArgumentException(name + " is not a public ClusterClock with a no-arg constructor");
    }
}

Try / catch

try { ctx.conclude(); } catch (ClusterException e) { if (e.getMessage().startsWith("failed to instantiate ClusterClock")) { ctx.clusterClock(new MillisecondClusterClock()); } }

Prevention

When it happens

Trigger: Setting -Daeron.cluster.clock (ClusterClock class name property) to a missing class, an abstract class, a class without a public no-arg constructor, or a class not implementing ClusterClock.

Common situations: Typo in the class name or package; enabling a high-resolution clock (e.g. CachedEpochClock/offset-clock experiments) and using the wrong class; fat-jar shading removing the clock class; upgrading Aeron where the clock class was renamed/removed.

Related errors


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

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModule.java:1800

            if (startupCanvassTimeoutNs / leaderHeartbeatTimeoutNs < 2)
            {
                throw new ClusterException(
                    "startupCanvassTimeoutNs=" + startupCanvassTimeoutNs +
                    " must be a multiple of leaderHeartbeatTimeoutNs=" + leaderHeartbeatTimeoutNs);
            }

            if (null == clusterClock)
            {
                final String clockClassName = System.getProperty(
                    CLUSTER_CLOCK_PROP_NAME, MillisecondClusterClock.class.getName());
                try
                {
                    clusterClock = (ClusterClock)Class.forName(clockClassName).getConstructor().newInstance();
                }
                catch (final Exception e)
                {
                    throw new ClusterException("failed to instantiate ClusterClock " + clockClassName, e);
                }
            }

            if (null == epochClock)
            {
                epochClock = SystemEpochClock.INSTANCE;
            }

            if (null == appVersionValidator)
            {
                appVersionValidator = AppVersionValidator.SEMANTIC_VERSIONING_VALIDATOR;
            }

            if (null == clusterTimeConsumerSupplier)
            {
                clusterTimeConsumerSupplier = (ctx) -> (timestamp) -> {};
            }

View on GitHub (pinned to 6d60124e15)