apache/druid · error · IllegalArgumentException

replaceTimeChunks must be null or nonempty; cannot be empty

Error message

replaceTimeChunks must be null or nonempty; cannot be empty

What it means

Validation in validateReplaceTimeChunksGranularityAligned: for MSQ REPLACE queries, replaceTimeChunks may be omitted entirely (null) to replace everything, or list specific time chunks to replace — but an empty list is ambiguous and therefore rejected at destination-construction time before any work is done.

Solutions

  1. Remove the replaceTimeChunks clause entirely from the REPLACE SQL to replace all time chunks.
  2. Provide at least one explicit time chunk interval (e.g. replaceTimeChunks = [2024-01-01/2024-02-01]) if a partial replace is intended.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/indexing/destination/DataSourceMSQDestination.java:276 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/18f37fa9d080a327. Report an issue: GitHub.

Appendix: source

Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/indexing/destination/DataSourceMSQDestination.java:276

  {
    return ShuffleSpecFactories.globalSortWithTargetSize(targetSize);
  }

  @Override
  public Optional<Resource> getDestinationResource()
  {
    return Optional.of(new Resource(getDataSource(), ResourceType.DATASOURCE));
  }

  private static void validateReplaceTimeChunksGranularityAligned(
      Granularity segmentGranularity,
      @Nullable List<Interval> replaceTimeChunks
  )
  {
    if (replaceTimeChunks != null) {
      // Verify that if replaceTimeChunks is provided, it is nonempty.
      if (replaceTimeChunks.isEmpty()) {
        throw new IAE("replaceTimeChunks must be null or nonempty; cannot be empty");
      }

      // Verify all provided time chunks are aligned with segmentGranularity.
      for (final Interval interval : replaceTimeChunks) {
        // ETERNITY gets a free pass.
        if (!Intervals.ETERNITY.equals(interval)) {
          final boolean startIsAligned =
              segmentGranularity.bucketStart(interval.getStart()).equals(interval.getStart());

          final boolean endIsAligned =
              segmentGranularity.bucketStart(interval.getEnd()).equals(interval.getEnd())
              || segmentGranularity.increment(segmentGranularity.bucketStart(interval.getEnd()))
                                   .equals(interval.getEnd());

          if (!startIsAligned || !endIsAligned) {
            throw new IAE(
                "Time chunk [%s] provided in replaceTimeChunks is not aligned with segmentGranularity [%s]",
                interval,

View on GitHub (pinned to 9b90983fd2)