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

  1. Check the ClusterTimeUnit value being passed; ensure it is one of SECONDS, MILLIS, MICROS, NANOS.
  2. Verify the mark file / persisted cluster data was produced by the same Aeron version as the running software.
  3. 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

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


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)