apache/druid · error · IllegalArgumentException
Granularity is not supported. [%s]
Error message
Granularity is not supported. [%s]
What it means
GranularityType.fromPeriod() converts a Joda Period into a GranularityType enum only when the period has exactly one non-zero component (e.g. PT1H or P1D). While scanning the period's field values it throws this IAE if it finds a second non-zero field, because a compound period like 'P1DT2H' does not map to any single granularity bucket.
Source
Thrown at processing/src/main/java/org/apache/druid/java/util/common/granularity/GranularityType.java:201
}
}
return false;
}
/**
* Note: This is only an estimate based on the values in period.
* This will not work for complicated periods that represent say 1 year 1 day
*/
public static GranularityType fromPeriod(Period period)
{
int[] vals = period.getValues();
int index = -1;
for (int i = 0; i < vals.length; i++) {
if (vals[i] != 0) {
if (index < 0) {
index = i;
} else {
throw new IAE("Granularity is not supported. [%s]", period);
}
}
}
switch (index) {
case 0:
return GranularityType.YEAR;
case 1:
if (vals[index] == 3) {
return GranularityType.QUARTER;
} else if (vals[index] == 1) {
return GranularityType.MONTH;
}
break;
case 2:
return GranularityType.WEEK;
case 3:
return GranularityType.DAY;View on GitHub (pinned to 9b90983fd2)
Solutions
- Use a simple Period with exactly one non-zero field, e.g. Period.parse("PT2H") instead of "PT1H30M"
- If a compound bucket is needed, pick the larger unit and set origin/timeZone on PeriodGranularity instead, or use an arbitrary-duration approach
- Parse the input period first and validate that at most one of getYears()..getMillis() is non-zero before calling fromPeriod
Example fix
// before
Granularity gran = GranularityType.fromPeriod(Period.parse("P1DT2H"));
// after
Granularity gran = GranularityType.fromPeriod(Period.parse("P1D")); // single non-zero field Defensive patterns
Strategy: validation
Validate before calling
static boolean isSimplePeriod(Period p) {
int nz = 0;
int[] f = {p.getYears(), p.getMonths(), p.getWeeks(), p.getDays(), p.getHours(), p.getMinutes(), p.getSeconds(), p.getMillis()};
for (int v : f) { if (v != 0) nz++; }
return nz == 1;
}
// call: if (!isSimplePeriod(period)) throw new IllegalArgumentException(...); Type guard
if (GranularityType.fromPeriod(period) == null || !isSimplePeriod(period)) { /* fallback */ } Try / catch
try { t = GranularityType.fromPeriod(period); } catch (IllegalArgumentException e) { /* fall back to PeriodGranularity or reject config */ } Prevention
- Reject compound periods (multiple non-zero fields) at config parse time
- Prefer Granularity enum JSON values over raw period strings in specs
- Unit-test granularity parsing with all user-facing config values
When it happens
Trigger: Calling GranularityType.fromPeriod(new Period("P1DT2H")) or any Period with two or more non-zero fields (weeks+days, hours+minutes, etc.). Also thrown when the period's fields don't align with the enum's supported magnitudes (e.g. PT90M after the switch falls through).
Common situations: Users supply compound query granularities like 'P1W2D' or 'PT1H30M' in JSON query specs or ingestion granularity configs; misconfigured period strings from external systems that normalize durations into compound periods.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Period cannot be converted to milliseconds as some fields ma
- Cannot accept both 'splitPoints' and 'numBins'
- bf1Length %d does not match bf2Length %d
- Invalid segment granularity [%s]
- Granularity [%s] is not supported
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/f5db76d99a077f5c.
Report an issue: GitHub.