{"record":{"id":"ff4762cdcc08be96","repo":"apache/druid","slug":"overlapping-intervals-s-s","errorCode":null,"errorMessage":"Overlapping intervals: %s, %s","messagePattern":"Overlapping intervals: (.+?), (.+?)","errorType":"validation","errorClass":"IAE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/indexer/granularity/ArbitraryGranularitySpec.java","lineNumber":58,"sourceCode":"  public ArbitraryGranularitySpec(\n      @JsonProperty(\"queryGranularity\") Granularity queryGranularity,\n      @JsonProperty(\"rollup\") Boolean rollup,\n      @JsonProperty(\"intervals\") @Nullable List<Interval> inputIntervals\n  )\n  {\n    super(inputIntervals, rollup);\n    this.queryGranularity = queryGranularity == null ? Granularities.NONE : queryGranularity;\n\n    lookupTableBucketByDateTime = new LookupIntervalBuckets(inputIntervals);\n\n    // Ensure intervals are non-overlapping (but they may abut each other)\n    final PeekingIterator<Interval> intervalIterator = Iterators.peekingIterator(sortedBucketIntervals().iterator());\n    while (intervalIterator.hasNext()) {\n      final Interval currentInterval = intervalIterator.next();\n      if (intervalIterator.hasNext()) {\n        final Interval nextInterval = intervalIterator.peek();\n        if (currentInterval.overlaps(nextInterval)) {\n          throw new IAE(\"Overlapping intervals: %s, %s\", currentInterval, nextInterval);\n        }\n      }\n    }\n  }\n\n  public ArbitraryGranularitySpec(\n      Granularity queryGranularity,\n      List<Interval> inputIntervals\n  )\n  {\n    this(queryGranularity, true, inputIntervals);\n  }\n\n  @Override\n  public Iterable<Interval> sortedBucketIntervals()\n  {\n    return () -> lookupTableBucketByDateTime.iterator();\n  }","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/indexer/granularity/ArbitraryGranularitySpec.java#L40-L76","documentation":"ArbitraryGranularitySpec validates that the sorted per-segment bucket intervals it generates do not overlap. During partitioning/granularity setup, if two consecutive bucket intervals overlap, this IAE is thrown because segment granularity buckets must be disjoint for correct data distribution. It indicates the granularity spec input or the underlying data intervals are inconsistent.","triggerScenarios":"Constructing or using an ArbitraryGranularitySpec whose granularities/buckets produce intersecting Intervals, e.g. duplicate or partially-overlapping intervals passed into the spec during batch ingestion task setup.","commonSituations":"Hand-written ingestion specs where arbitrary intervals were listed twice or with offset mistakes; programmatic spec generation producing overlapping segmentGranular intervals; time zone/DST math shifting interval boundaries so adjacent buckets intersect.","solutions":["Inspect the two intervals printed in the message and fix the granularity spec so intervals are disjoint (no overlaps, no duplicates).","If intervals were supplied programmatically, sort and deduplicate/merge them before building the spec.","Use a standard GranularitySpec (e.g. uniformGranularity) if fixed granularities are sufficient and custom intervals are error-prone."],"exampleFix":"// before\nList<Interval> intervals = Arrays.asList(\n  Intervals.of(\"2024-01-01/2024-01-05\"),\n  Intervals.of(\"2024-01-03/2024-01-10\")); // overlap\n// after\nList<Interval> intervals = Arrays.asList(\n  Intervals.of(\"2024-01-01/2024-01-05\"),\n  Intervals.of(\"2024-01-05/2024-01-10\")); // adjacent, non-overlapping","handlingStrategy":"validation","validationCode":"for (int i = 1; i < intervals.size(); i++) {\n  if (intervals.get(i - 1).overlaps(intervals.get(i))) {\n    throw new IllegalArgumentException(\"Overlapping intervals: \" + intervals.get(i - 1) + \", \" + intervals.get(i));\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Sort and merge intervals before building the granularity spec","Never list the same interval twice","Watch DST/timezone boundary arithmetic when generating intervals"],"tags":["ingestion","granularity","configuration","invalid-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}