{"record":{"id":"df740874e4fe92ae","repo":"apache/druid","slug":"s-is-an-invalid-granularity-string","errorCode":null,"errorMessage":"[%s] is an invalid granularity string.","messagePattern":"\\[(.+?)\\] is an invalid granularity string\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/catalog/model/CatalogUtils.java","lineNumber":81,"sourceCode":"   * are either the usual descriptive strings (in any case), or an ISO period.\n   * For the odd interval, the interval name is also accepted (for the other\n   * intervals, the interval name is the descriptive string).\n   */\n  public static Granularity asDruidGranularity(@Nonnull String value)\n  {\n    if (value.equalsIgnoreCase(DatasourceDefn.ALL_GRANULARITY)) {\n      return Granularities.ALL;\n    }\n    Granularity granularity;\n    try {\n      granularity = Granularity.fromString(value);\n    }\n    catch (IllegalArgumentException e) {\n      try {\n        granularity = new PeriodGranularity(new Period(value), null, null);\n      }\n      catch (IllegalArgumentException e2) {\n        throw new IAE(\"[%s] is an invalid granularity string.\", value);\n      }\n    }\n\n    return granularity;\n  }\n\n  /**\n   * {@code String}-to-{@code List<String>} conversion. The string can contain zero items,\n   * one items, or a list. The list items are separated by a comma and optional\n   * whitespace.\n   */\n  public static List<String> stringToList(String value)\n  {\n    if (value == null) {\n      return null;\n    }\n    return Arrays.asList(value.split(\",\\\\s*\"));\n  }","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/catalog/model/CatalogUtils.java#L63-L99","documentation":"Thrown by CatalogUtils.asDruidGranularity when a granularity string cannot be parsed either as a named Druid granularity (GranularityType/fromString throws IllegalArgumentException) nor as an ISO-8601 period (new Period(value) also throws IllegalArgumentException). It signals the catalog table property holds an unparseable granularity value.","triggerScenarios":"Setting a table's granularity property to a string that is neither a standard name (second, minute, hour, day, week, month, quarter, year, all) nor a valid ISO-8601 period such as PT1H or P1D - e.g. '1day', 'hourly', '1 hour', or an empty string.","commonSituations":"Users authoring catalog/table specs by hand assuming human-friendly names like 'daily' work, SQL catalog updates with typos, tool-generated specs emitting locale-formatted durations.","solutions":["Use a standard granularity name (e.g. 'day') or a valid ISO-8601 period (e.g. 'P1D', 'PT6H')","Validate the string with new Period(value) or GranularityType.fromString before persisting it","Fix the offending catalog table property and retry the operation"],"exampleFix":"// before\n\"granularity\": \"1 day\"\n// after\n\"granularity\": \"P1D\"","handlingStrategy":"validation","validationCode":"boolean valid = false;\ntry {\n  org.apache.druid.java.util.common.granularity.GranularityType.fromString(value);\n  valid = true;\n} catch (IllegalArgumentException ignore) {\n  try { new org.joda.time.Period(value); valid = true; }\n  catch (IllegalArgumentException ignore2) { }\n}\nif (!valid) throw new IllegalArgumentException(\"Bad granularity: \" + value);","typeGuard":null,"tryCatchPattern":"try {\n  Granularity g = CatalogUtils.asDruidGranularity(value);\n} catch (IllegalArgumentException e) {\n  log.error(\"Granularity '{}' is neither a named granularity nor an ISO period\", value);\n}","preventionTips":["Accept only named granularities or ISO-8601 periods (P1D, PT6H) in user input","Add UI/API-side validation before persisting granularity properties","Never store locale-formatted or human-friendly duration strings ('1 day', 'hourly')"],"tags":["granularity","catalog","validation"],"backgroundTag":"invalid-argument-format","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"}