apache/pulsar · error · IllegalArgumentException

Invalid time unit '<lastChar>'

Error message

Invalid time unit '<lastChar>'

What it means

RelativeTimeUtil.parseRelativeTimeInSeconds parses strings like '60s', '5m', '2h', '7d', '2w', '1y' into seconds. The last character is taken as the time unit; if it is alphabetic but not one of s/m/h/d/w/y (case-insensitive), the parser throws this IllegalArgumentException. Note that months are intentionally unsupported, so 'M' and other letters like 'x' or 'z' are rejected.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/RelativeTimeUtil.java:65

        long duration = Long.parseLong(relativeTime.substring(0, lastIndex));

        switch (timeUnit) {
        case 's':
            return duration;
        case 'm':
            return TimeUnit.MINUTES.toSeconds(duration);
        case 'h':
            return TimeUnit.HOURS.toSeconds(duration);
        case 'd':
            return TimeUnit.DAYS.toSeconds(duration);
        case 'w':
            return 7 * TimeUnit.DAYS.toSeconds(duration);
        // No unit for months
        case 'y':
            return 365 * TimeUnit.DAYS.toSeconds(duration);
        default:
            throw new IllegalArgumentException("Invalid time unit '" + lastChar + "'");
        }
    }

    /**
     * Convert nanoseconds to seconds and keep three decimal places.
     * @param ns
     * @return seconds
     */
    public static double nsToSeconds(long ns) {
        double seconds = (double) ns / 1_000_000_000;
        BigDecimal bd = new BigDecimal(seconds);
        return bd.setScale(3, RoundingMode.HALF_UP).doubleValue();
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Fix the input string to use only supported units: s, m, h, d, w, or y (e.g. '30m' instead of '30M').
  2. Express months as days or weeks (e.g. '30d') since months are not a supported unit.
  3. Strip surrounding whitespace/typos so the string ends with a valid single-letter unit.
  4. Validate the unit character before calling the parser in user-facing code.

Example fix

// before
long seconds = RelativeTimeUtil.parseRelativeTimeInSeconds("30M");
// after
long seconds = RelativeTimeUtil.parseRelativeTimeInSeconds("30d");
Defensive patterns

Strategy: validation

Validate before calling

private static final java.util.Set<Character> VALID_UNITS = java.util.Set.of('s','m','h','d','w','y');
static long safeParseRelativeTime(String input) {
    String trimmed = input.trim();
    if (trimmed.isEmpty()) throw new IllegalArgumentException("expiry time cannot be empty");
    char last = Character.toLowerCase(trimmed.charAt(trimmed.length() - 1));
    if (Character.isAlphabetic(last) && !VALID_UNITS.contains(last)) {
        throw new IllegalArgumentException("Invalid time unit '" + last + "'; use s, m, h, d, w, or y");
    }
    return RelativeTimeUtil.parseRelativeTimeInSeconds(trimmed);
}

Type guard

static boolean isValidRelativeTimeString(String s) {
    if (s == null || s.isEmpty()) return false;
    char last = Character.toLowerCase(s.charAt(s.length() - 1));
    if (!Character.isAlphabetic(last)) return true; // no unit -> seconds
    return "smdwy".indexOf(last) >= 0;
}

Try / catch

try {
    long seconds = RelativeTimeUtil.parseRelativeTimeInSeconds(userInput);
} catch (IllegalArgumentException e) {
    LOG.error("Invalid relative time '{}' (units: s, m, h, d, w, y)", userInput, e);
    throw new ConfigurationException("Invalid time value: " + userInput, e);
}

Prevention

When it happens

Trigger: Calling parseRelativeTimeInSeconds with a string ending in a letter other than s, m, h, d, w, or y (e.g. '30M' for minutes uppercase-collision concerns or months, '1mo', '10x', '5min'). Any user/config supplied relative time value (e.g. TTL, retention, expiry settings) with an unrecognized unit suffix.

Common situations: Users write '30M' or '1mo' expecting months or minutes; config files carry units like 'ms', 'min', or 'sec' carried over from other tools; typo in unit suffix ('2hh'); locale or copy-paste issues introduce odd trailing characters.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/7b5b6c64a1be205a. Report an issue: GitHub.