{"record":{"id":"c0cbd955c0b793fe","repo":"apache/druid","slug":"adjacent-intervals-are-not-sorted-s-s","errorCode":null,"errorMessage":"Adjacent intervals are not sorted [%s,%s]","messagePattern":"Adjacent intervals are not sorted \\[(.+?),(.+?)\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/java/util/common/JodaUtils.java","lineNumber":163,"sourceCode":"            DateTime currEnd = currInterval.getEnd();\n            currInterval = new Interval(\n                currInterval.getStart(),\n                nextEnd.isAfter(currEnd) ? nextEnd : currEnd\n            );\n            peekingIterator.next();\n          } else {\n            break;\n          }\n        }\n        return currInterval;\n      }\n    };\n  }\n\n  private static void verifyAscendingSortOrder(Interval previous, Interval current)\n  {\n    if (previous != null && previous.isAfter(current)) {\n      throw new IAE(\"Adjacent intervals are not sorted [%s,%s]\", previous, current);\n    }\n  }\n\n  public static Interval umbrellaInterval(Iterable<Interval> intervals)\n  {\n    boolean emptyIntervals = true;\n    DateTimeComparator dateTimeComp = DateTimeComparator.getInstance();\n    DateTime minStart = new DateTime(Long.MAX_VALUE, ISOChronology.getInstanceUTC());\n    DateTime maxEnd = new DateTime(Long.MIN_VALUE, ISOChronology.getInstanceUTC());\n\n    for (Interval interval : intervals) {\n      emptyIntervals = false;\n      minStart = Collections.min(ImmutableList.of(minStart, interval.getStart()), dateTimeComp);\n      maxEnd = Collections.max(ImmutableList.of(maxEnd, interval.getEnd()), dateTimeComp);\n    }\n\n    if (emptyIntervals) {\n      throw new IllegalArgumentException(\"Empty list of intervals\");","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/java/util/common/JodaUtils.java#L145-L181","documentation":"JodaUtils.mergeIntervals requires its input intervals to be sorted in ascending order; verifyAscendingSortOrder throws this IAE when a previous interval is strictly after (isAfter) the current one. The merging algorithm relies on sortedness to detect abutting/overlapping intervals in a single pass, so unsorted input would produce wrong results and is rejected.","triggerScenarios":"Calling mergeIntervals with a list like [2023-01-02/2023-01-03, 2023-01-01/2023-01-02] where an earlier interval follows a later one; any partially sorted or reversed interval collection.","commonSituations":"Intervals accumulated from unordered sources (segment lists from different workers, map iteration order, user-specified rules) and passed directly without sorting.","solutions":["Sort before merging: intervals.sort(Interval::compareTo) or intervals.stream().sorted().collect(...)","If using Java, build a TreeSet<Interval> from the input to get sorted, deduplicated intervals","Verify the upstream producer emits chronologically ordered intervals"],"exampleFix":"// before\nJodaUtils.mergeIntervals(Arrays.asList(later, earlier)); // IAE\n// after\nList<Interval> sorted = intervals.stream().sorted().collect(Collectors.toList());\nJodaUtils.mergeIntervals(sorted);","handlingStrategy":"validation","validationCode":"List<Interval> sorted = intervals.stream().sorted().collect(Collectors.toList());\nJodaUtils.mergeIntervals(sorted);","typeGuard":"static boolean isSorted(List<Interval> list) {\n  for (int i = 1; i < list.size(); i++) {\n    if (list.get(i - 1).isAfter(list.get(i))) return false;\n  }\n  return true;\n}","tryCatchPattern":"try {\n  return JodaUtils.mergeIntervals(intervals);\n} catch (IllegalArgumentException e) {\n  List<Interval> sorted = new ArrayList<>(intervals);\n  sorted.sort(Comparator.naturalOrder());\n  return JodaUtils.mergeIntervals(sorted);\n}","preventionTips":["Always sort interval lists before merging — the utility requires ascending order","Collect intervals into a TreeSet<Interval> to guarantee ordering at construction","Never assume upstream producers emit chronologically ordered intervals"],"tags":["intervals","sorting","joda-time"],"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-17T15:17:12.973Z"}