aeron-io/aeron · error · ClusterException
invalid TimerServiceSupplier
Error message
invalid TimerServiceSupplier: <timeServiceClassName>
What it means
ConsensusModule.Configuration.newTimerServiceSupplier() instantiates a TimerServiceSupplier by class name, accepting only known implementations (e.g. PriorityHeapTimerServiceSupplier). An unrecognized class name is rejected with ClusterException "invalid TimerServiceSupplier".
Solutions
- Use the built-in name PriorityHeapTimerServiceSupplier.class.getName().
- Correct the typo in the configured class name.
- Remove the property to use the default timer service supplier.
- If a custom supplier is required, construct it programmatically instead of by class name, or upgrade to a version supporting it.
Example fix
// before
System.setProperty("aeron.cluster.timer.service.supplier", "com.acme.MyTimerSupplier");
// after
System.setProperty("aeron.cluster.timer.service.supplier",
"io.aeron.cluster.service.PriorityHeapTimerServiceSupplier"); Defensive patterns
Strategy: validation
Validate before calling
String name = System.getProperty("aeron.cluster.timer.service.supplier", "");
if (!name.isEmpty() && !"io.aeron.cluster.service.PriorityHeapTimerServiceSupplier".equals(name)) {
throw new IllegalArgumentException("unsupported timer service supplier: " + name);
} Try / catch
try { ConsensusModule.launch(ctx); } catch (ClusterException e) { if (e.getMessage().startsWith("invalid TimerServiceSupplier")) { log.error("check aeron.cluster.timer.service.supplier value"); } throw e; } Prevention
- Use the fully-qualified name of a built-in supplier
- Remove the property to get the default
- Load the class with Class.forName as a pre-flight check
When it happens
Trigger: Setting the timer service supplier property (aeron.cluster.timer.service.supplier) to a class name that is not one of the built-in suppliers and either is not on the classpath or is not a supported name.
Common situations: Typo in the fully-qualified class name; custom TimerServiceSupplier supplied by name without the module supporting arbitrary names; property copied from an incompatible Aeron version.
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
- ClusterBackup.Context.catchupEndpoint must be set
- local archive control must be IPC
- log publication at max position: term-length=
- logChannel must not contain
- logChannel must not contain
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/903eeb96fa4cf080.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModule.java:4606
private TimerServiceSupplier getTimerServiceSupplierFromSystemProperty()
{
final String timeServiceClassName = Configuration.timerServiceSupplier();
if (WheelTimerServiceSupplier.class.getName().equals(timeServiceClassName))
{
return new WheelTimerServiceSupplier(
clusterClock.timeUnit(),
0,
findNextPositivePowerOfTwo(
clusterClock.timeUnit().convert(wheelTickResolutionNs, TimeUnit.NANOSECONDS)),
ticksPerWheel);
}
else if (PriorityHeapTimerServiceSupplier.class.getName().equals(timeServiceClassName))
{
return new PriorityHeapTimerServiceSupplier();
}
throw new ClusterException("invalid TimerServiceSupplier: " + timeServiceClassName);
}
private void validateLogChannel()
{
final ChannelUri logChannelUri = parse(logChannel);
if (logChannelUri.containsKey(INITIAL_TERM_ID_PARAM_NAME))
{
throw new ConfigurationException("logChannel must not contain: " + INITIAL_TERM_ID_PARAM_NAME);
}
if (logChannelUri.containsKey(TERM_ID_PARAM_NAME))
{
throw new ConfigurationException("logChannel must not contain: " + TERM_ID_PARAM_NAME);
}
if (logChannelUri.containsKey(TERM_OFFSET_PARAM_NAME))
{
throw new ConfigurationException("logChannel must not contain: " + TERM_OFFSET_PARAM_NAME);
}
}View on GitHub (pinned to 6d60124e15)