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
- Fix the system property to a fully-qualified ClusterClock implementation with a public no-arg constructor
- Remove the property to fall back to MillisecondClusterClock
- 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
- Prefer ctx.clusterClock(new ...) over the reflection-based system property
- Keep the clock class in the same artifact/classpath as the cluster
- Test custom clocks with a plain new-instance check
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
- failed to create Checksum instance for class: " + className
- catalogFileSyncLevel
- invalid fileIoMaxLength=
- Archive.Context.controlChannel must be set
- Archive.Context.controlChannel must be UDP media: uri=
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)