{"record":{"id":"32d6e07f9ae93243","repo":"apache/druid","slug":"invalid-segment-granularity-s","errorCode":null,"errorMessage":"Invalid segment granularity [%s]","messagePattern":"Invalid segment granularity \\[(.+?)\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"multi-stage-query/src/main/java/org/apache/druid/msq/querykit/QueryKitUtils.java","lineNumber":99,"sourceCode":"   * Enables QueryKit-generated processors to understand which output column will be mapped to\n   * {@link org.apache.druid.segment.column.ColumnHolder#TIME_COLUMN_NAME}. Necessary because {@link QueryKit}\n   * does not get direct access to {@link ColumnMappings}.\n   */\n  public static final String CTX_TIME_COLUMN_NAME = \"__timeColumn\";\n\n  public static Granularity getSegmentGranularityFromContext(\n      final ObjectMapper objectMapper,\n      @Nullable final Map<String, Object> context\n  )\n  {\n    final Object o = context == null ? null : context.get(DruidSqlInsert.SQL_INSERT_SEGMENT_GRANULARITY);\n\n    if (o instanceof String) {\n      try {\n        return objectMapper.readValue((String) o, Granularity.class);\n      }\n      catch (JsonProcessingException e) {\n        throw new ISE(\"Invalid segment granularity [%s]\", o);\n      }\n    } else if (o == null) {\n      return Granularities.ALL;\n    } else {\n      throw new ISE(\"Invalid segment granularity [%s]\", o);\n    }\n  }\n\n  /**\n   * Adds bucketing by {@link #SEGMENT_GRANULARITY_COLUMN} to a {@link ClusterBy} if needed.\n   */\n  public static ClusterBy clusterByWithSegmentGranularity(\n      final ClusterBy clusterBy,\n      final Granularity segmentGranularity\n  )\n  {\n    if (Granularities.ALL.equals(segmentGranularity)) {\n      return clusterBy;","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/multi-stage-query/src/main/java/org/apache/druid/msq/querykit/QueryKitUtils.java#L81-L117","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use a valid granularity string: \"second\", \"minute\", \"hour\", \"day\", \"week\", \"month\", \"quarter\", \"year\", or \"all\".","Provide a period string instead, e.g. \"P1D\", which deserializes to a PeriodGranularity.","Check the exact context key and value being sent by the client/tool and correct the typo."],"exampleFix":"// before\nqueryContext.put(\"segmentGranularity\", \"daily\");\n// after\nqueryContext.put(\"segmentGranularity\", \"day\");","handlingStrategy":"validation","validationCode":"String g = (String) context.get(\"segmentGranularity\");\nif (g != null && !java.util.List.of(\"second\",\"minute\",\"fifteen_minute\",\"thirty_minute\",\"hour\",\"day\",\"week\",\"month\",\"quarter\",\"year\",\"all\").contains(g)) {\n  throw new IllegalArgumentException(\"Invalid segmentGranularity: \" + g);\n}","typeGuard":null,"tryCatchPattern":"try {\n  granularity = QueryKitUtils.getSegmentGranularityFromQueryContext(query, objectMapper);\n} catch (IllegalStateException e) {\n  granularity = Granularities.ALL; // or fail fast with a clear message\n}","preventionTips":["Only use documented granularity names or ISO period strings (e.g. P1D).","Validate client-supplied context values before query submission.","Beware typos like \"daily\" or locale/case variants."],"tags":["druid","msq","granularity","context","parsing"],"backgroundTag":"invalid-config-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}