aeron-io/aeron · error · IllegalArgumentException
unsupported time unit
Error message
unsupported time unit: <clusterTimeUnit>
What it means
ClusterClock.map() converts a ClusterTimeUnit enum value into a java.util.concurrent.TimeUnit. The enum switch only covers SECONDS, MILLIS, MICROS and NANOS; if a ClusterTimeUnit value outside those is passed (e.g. a future/unknown ordinal decoded from a mark file or log header), IllegalArgumentException is thrown. It signals an unrecognized time unit value reaching the mapping function.
Solutions
- Check the ClusterTimeUnit value being passed; ensure it is one of SECONDS, MILLIS, MICROS, NANOS.
- Verify the mark file / persisted cluster data was produced by the same Aeron version as the running software.
- If you control the code, validate the unit before calling ClusterClock.map and default to a supported unit.
Example fix
// before
TimeUnit unit = ClusterClock.map(clusterTimeUnit);
// after
if (clusterTimeUnit == null || clusterTimeUnit == ClusterTimeUnit.UNKNOWN) {
clusterTimeUnit = ClusterTimeUnit.MILLIS; // or fail fast with a clear message
}
TimeUnit unit = ClusterClock.map(clusterTimeUnit); Defensive patterns
Strategy: validation
Validate before calling
// java
if (clusterTimeUnit == null) throw new IllegalArgumentException("clusterTimeUnit required");
switch (clusterTimeUnit) {
case SECONDS: case MILLIS: case MICROS: case NANOS: break;
default: throw new IllegalArgumentException("unsupported ClusterTimeUnit: " + clusterTimeUnit);
}
TimeUnit unit = ClusterClock.map(clusterTimeUnit); Type guard
static boolean isSupported(ClusterTimeUnit u) {
return u == ClusterTimeUnit.SECONDS || u == ClusterTimeUnit.MILLIS ||
u == ClusterTimeUnit.MICROS || u == ClusterTimeUnit.NANOS;
} Try / catch
try {
TimeUnit unit = ClusterClock.map(clusterTimeUnit);
} catch (IllegalArgumentException e) {
// fall back to a default unit or surface a config error
TimeUnit unit = TimeUnit.MILLISECONDS;
} Prevention
- Never pass enum values decoded from persisted files without validating against the current schema.
- Reject UNKNOWN/missing time units at configuration load time.
- Keep the Aeron version identical across cluster nodes to avoid new enum values.
When it happens
Trigger: Calling ClusterClock.map(clusterTimeUnit) with a ClusterTimeUnit value not handled by the switch — typically a null reference unwrapped oddly, or an UNKNOWN/invalid enum value decoded from persisted cluster data whose schema is newer or corrupt.
Common situations: Restoring a cluster mark file or snapshot written by a different Aeron version that introduced a new ClusterTimeUnit; hand-crafted tests passing null or UNKNOWN; corrupt stored clusterTimeUnit field.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- name + " cannot be negative: value=" + value
- unsupported time unit
- Invalid errorBufferLength
- gapLength must be smaller than gapRadix
- ControlSession.RESPONSE_NOT_CONNECTED_MSG + ": " + session
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/aab0fcb3711f805a.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/service/ClusterClock.java:135
* @return a corresponding {@link TimeUnit}, if {@link ClusterTimeUnit#NULL_VAL} is passed then defaults
* to {@link TimeUnit#MILLISECONDS}.
*/
static TimeUnit map(final ClusterTimeUnit clusterTimeUnit)
{
switch (clusterTimeUnit)
{
case NULL_VAL:
case MILLIS:
return TimeUnit.MILLISECONDS;
case MICROS:
return TimeUnit.MICROSECONDS;
case NANOS:
return TimeUnit.NANOSECONDS;
}
throw new IllegalArgumentException("unsupported time unit: " + clusterTimeUnit);
}
}
View on GitHub (pinned to 6d60124e15)