{"record":{"id":"407519748a23cb58","repo":"apache/druid","slug":"null-empty-intervals","errorCode":null,"errorMessage":"null/empty intervals","messagePattern":"null/empty intervals","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/metadata/IndexerSQLMetadataStorageCoordinator.java","lineNumber":194,"sourceCode":"      DateTime maxUpdatedTime,\n      int maxResultSize,\n      int maxSegmentsToScan\n  )\n  {\n    return inReadOnlyTransaction(\n        sql -> sql.retrieveSomeUnusedSegmentIntervals(maxUpdatedTime, maxResultSize, maxSegmentsToScan)\n    );\n  }\n\n  @Override\n  public Set<DataSegment> retrieveUsedSegmentsForIntervals(\n      final String dataSource,\n      final List<Interval> intervals,\n      final Segments visibility\n  )\n  {\n    if (intervals == null || intervals.isEmpty()) {\n      throw new IAE(\"null/empty intervals\");\n    }\n    return doRetrieveUsedSegments(dataSource, intervals, visibility);\n  }\n\n  @Override\n  public Set<DataSegment> retrieveAllUsedSegments(String dataSource, Segments visibility)\n  {\n    return doRetrieveUsedSegments(dataSource, Collections.emptyList(), visibility);\n  }\n\n  /**\n   * @param intervals empty list means unrestricted interval.\n   */\n  private Set<DataSegment> doRetrieveUsedSegments(\n      final String dataSource,\n      final List<Interval> intervals,\n      final Segments visibility\n  )","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/metadata/IndexerSQLMetadataStorageCoordinator.java#L176-L212","documentation":"IndexerSQLMetadataStorageCoordinator.retrieveUsedSegmentsForIntervals requires a non-null, non-empty interval list before querying the metadata store. Null or empty input throws IAE('null/empty intervals') because the SQL query built from the intervals would be meaningless.","triggerScenarios":"Calling retrieveUsedSegmentsForIntervals(dataSource, null, visibility) or with an empty List<Interval>, usually when a caller computed segments intervals from an empty query/timeline result.","commonSituations":"Batch task or coordinator code passing an empty interval list derived from no input shards; API callers requesting used segments without specifying any intervals.","solutions":["Check intervals for null/empty before calling and short-circuit to return an empty segment set","Fix the upstream interval computation so it produces at least one Interval","If 'all segments' is intended, use retrieveAllUsedSegments instead"],"exampleFix":"// before\nSet<DataSegment> segments = coordinator.retrieveUsedSegmentsForIntervals(ds, intervals, Segments.ONLY_VISIBLE);\n// after\nSet<DataSegment> segments = (intervals == null || intervals.isEmpty())\n    ? Collections.emptySet()\n    : coordinator.retrieveUsedSegmentsForIntervals(ds, intervals, Segments.ONLY_VISIBLE);","handlingStrategy":"validation","validationCode":"if (intervals == null || intervals.isEmpty()) { return Collections.emptySet(); }","typeGuard":"boolean hasIntervals = intervals != null && !intervals.isEmpty();","tryCatchPattern":"try { segments = coordinator.retrieveUsedSegmentsForIntervals(ds, intervals, visibility); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"null/empty intervals\")) { segments = Collections.emptySet(); } else { throw e; } }","preventionTips":["Validate interval lists before metadata-store queries","Treat empty input as an empty result early in the calling code","Use retrieveAllUsedSegments when the intent is to fetch everything"],"tags":["java","metadata","segments","validation"],"backgroundTag":"empty-required-field","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"}