apache/iceberg · error · IllegalArgumentException
Invalid time unit
Error message
Invalid time unit: %s
What it means
TimerResultParser.toTimeUnit converts the 'timeUnit' JSON field of a timer result into java.util.concurrent.TimeUnit using TimeUnit.valueOf on the upper-cased string. If the string is not a valid TimeUnit constant name, IllegalArgumentException('Invalid time unit: ...') is thrown, indicating malformed metrics JSON.
Solutions
- Use standard TimeUnit constant names in the JSON: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
- Fix the producer of the metrics JSON to emit TimeUnit.valueOf-compatible names
- Validate/sanitize the timeUnit string before parsing, mapping abbreviations ('ns' -> 'NANOSECONDS') yourself
- Catch IllegalArgumentException when parsing untrusted metrics files and skip or remap the offending timer
Example fix
// before
String unit = "ns"; // fails
// after
String unit = switch (raw) {
case "ns" -> "NANOSECONDS";
case "ms" -> "MILLISECONDS";
default -> raw.toUpperCase(Locale.ROOT);
}; Defensive patterns
Strategy: validation
Validate before calling
boolean validTimeUnit(String s) {
try { TimeUnit.valueOf(s.toUpperCase(Locale.ROOT)); return true; }
catch (IllegalArgumentException | NullPointerException e) { return false; }
} Try / catch
try {
TimerResultParser.fromJson(json);
} catch (IllegalArgumentException e) {
LOG.warn("Skipping malformed timer: {}", e.getMessage());
} Prevention
- Emit standard TimeUnit constant names (NANOSECONDS, MILLISECONDS, ...) in metrics JSON
- Validate metrics files from third-party producers before parsing
- Map abbreviations (ns/ms) to TimeUnit names at ingestion
When it happens
Trigger: Parsing a TimerResult JSON (from a metrics report) whose timeUnit field is misspelled, in an unexpected format (e.g. 'nanos', 'ns', 'milli-seconds'), or produced by a different/writer version using non-standard unit names.
Common situations: Hand-edited or third-party-generated metrics JSON; reading metrics files produced by another framework; unit strings like 'NANOSECOND' (singular) or lowercase abbreviations.
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
- Invalid value for (negative): , falling back to
- Cannot get metrics from file format
- Cannot initialize MetricsReporter, missing no-arg…
- Cannot initialize MetricsReporter
- Cannot load Dropwizard metrics; is…
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/1d967a878e7ccb8f.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/metrics/TimerResultParser.java:117
long duration = JsonUtil.getLong(TOTAL_DURATION, timer);
return TimerResult.of(unit, toDuration(duration, unit), count);
}
@VisibleForTesting
static long fromDuration(Duration duration, TimeUnit unit) {
return unit.convert(duration.toNanos(), TimeUnit.NANOSECONDS);
}
@VisibleForTesting
static Duration toDuration(long val, TimeUnit unit) {
return Duration.of(val, toChronoUnit(unit));
}
private static TimeUnit toTimeUnit(String timeUnit) {
try {
return TimeUnit.valueOf(timeUnit.toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(String.format("Invalid time unit: %s", timeUnit), e);
}
}
private static ChronoUnit toChronoUnit(TimeUnit unit) {
switch (unit) {
case NANOSECONDS:
return ChronoUnit.NANOS;
case MICROSECONDS:
return ChronoUnit.MICROS;
case MILLISECONDS:
return ChronoUnit.MILLIS;
case SECONDS:
return ChronoUnit.SECONDS;
case MINUTES:
return ChronoUnit.MINUTES;
case HOURS:
return ChronoUnit.HOURS;
case DAYS:View on GitHub (pinned to 86d9c8fc54)