apache/druid · error · IllegalStateException

Invalid segment granularity [%s]

Error message

Invalid segment granularity [%s]

What it means

Thrown by QueryKitUtils.getSegmentGranularityFromContext when the segment granularity value from the query context is a String that cannot be JSON-deserialized into a Granularity. Druid expects the context value to be a valid granularity string (e.g. "day") or a Granularity object; anything unparsable is rejected.

Source

Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/querykit/QueryKitUtils.java:99

   * Enables QueryKit-generated processors to understand which output column will be mapped to
   * {@link org.apache.druid.segment.column.ColumnHolder#TIME_COLUMN_NAME}. Necessary because {@link QueryKit}
   * does not get direct access to {@link ColumnMappings}.
   */
  public static final String CTX_TIME_COLUMN_NAME = "__timeColumn";

  public static Granularity getSegmentGranularityFromContext(
      final ObjectMapper objectMapper,
      @Nullable final Map<String, Object> context
  )
  {
    final Object o = context == null ? null : context.get(DruidSqlInsert.SQL_INSERT_SEGMENT_GRANULARITY);

    if (o instanceof String) {
      try {
        return objectMapper.readValue((String) o, Granularity.class);
      }
      catch (JsonProcessingException e) {
        throw new ISE("Invalid segment granularity [%s]", o);
      }
    } else if (o == null) {
      return Granularities.ALL;
    } else {
      throw new ISE("Invalid segment granularity [%s]", o);
    }
  }

  /**
   * Adds bucketing by {@link #SEGMENT_GRANULARITY_COLUMN} to a {@link ClusterBy} if needed.
   */
  public static ClusterBy clusterByWithSegmentGranularity(
      final ClusterBy clusterBy,
      final Granularity segmentGranularity
  )
  {
    if (Granularities.ALL.equals(segmentGranularity)) {
      return clusterBy;

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Use a valid granularity string: "second", "minute", "hour", "day", "week", "month", "quarter", "year", or "all".
  2. Provide a period string instead, e.g. "P1D", which deserializes to a PeriodGranularity.
  3. Check the exact context key and value being sent by the client/tool and correct the typo.

Example fix

// before
queryContext.put("segmentGranularity", "daily");
// after
queryContext.put("segmentGranularity", "day");
Defensive patterns

Strategy: validation

Validate before calling

String g = (String) context.get("segmentGranularity");
if (g != null && !java.util.List.of("second","minute","fifteen_minute","thirty_minute","hour","day","week","month","quarter","year","all").contains(g)) {
  throw new IllegalArgumentException("Invalid segmentGranularity: " + g);
}

Try / catch

try {
  granularity = QueryKitUtils.getSegmentGranularityFromQueryContext(query, objectMapper);
} catch (IllegalStateException e) {
  granularity = Granularities.ALL; // or fail fast with a clear message
}

Prevention

When it happens

Trigger: Setting the context key holding segment granularity to a misspelled or malformed string such as "daily", "DAY" with wrong casing handled differently by JSON binding, or an arbitrary JSON object type that ObjectMapper fails to deserialize.

Common situations: BI tools or scripts injecting granularity context values with typos; API callers passing mixed-case or non-standard granularity names; upgrades where custom granularity classes are not on the classpath.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/32d6e07f9ae93243. Report an issue: GitHub.