apache/druid · error · ISE

Could not find interval for timestamp [%s]

Error message

Could not find interval for timestamp [%s]

What it means

LocalSegmentAllocator assigns each ingested row to a segment bucket based on the granularitySpec's interval-to-version mapping. When a row's timestamp falls outside all configured bucket intervals, bucketInterval returns empty and the allocator throws instead of silently dropping the row.

Source

Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/LocalSegmentAllocator.java:64

class LocalSegmentAllocator implements SegmentAllocatorForBatch
{
  private final SegmentAllocator internalAllocator;
  private final SequenceNameFunction sequenceNameFunction;

  LocalSegmentAllocator(TaskToolbox toolbox, String taskId, String dataSource, GranularitySpec granularitySpec) throws IOException
  {
    final Map<Interval, String> intervalToVersion = toolbox
        .getTaskActionClient()
        .submit(new LockListAction())
        .stream()
        .collect(Collectors.toMap(TaskLock::getInterval, TaskLock::getVersion));
    final Map<Interval, MutableInt> counters = Maps.newHashMapWithExpectedSize(intervalToVersion.size());

    internalAllocator = (row, sequenceName, previousSegmentId, skipSegmentLineageCheck) -> {
      final DateTime timestamp = row.getTimestamp();
      Optional<Interval> maybeInterval = granularitySpec.bucketInterval(timestamp);
      if (!maybeInterval.isPresent()) {
        throw new ISE("Could not find interval for timestamp [%s]", timestamp);
      }

      final Interval interval = maybeInterval.get();
      final String version = intervalToVersion
          .entrySet()
          .stream()
          .filter(entry -> entry.getKey().contains(interval))
          .map(Entry::getValue)
          .findFirst()
          .orElseThrow(() -> new ISE("Cannot find a version for interval[%s]", interval));

      final int partitionId = counters.computeIfAbsent(interval, x -> new MutableInt()).getAndIncrement();
      return new SegmentIdWithShardSpec(
          dataSource,
          interval,
          version,
          new BuildingNumberedShardSpec(partitionId)
      );

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Widen the task's granularitySpec.intervals to include all expected timestamps
  2. Increase windowPeriod to absorb late-arriving data, or pre-filter/transform out-of-window rows
  3. Ensure shardSpecs cover every interval in the configured ranges when using a local allocator in tests/local runs

Example fix

// before
"granularitySpec": {"intervals": ["2024-01-01/2024-01-02"], "windowPeriod": "PT30M"}
// after
"granularitySpec": {"intervals": ["2023-12-31/2024-01-03"], "windowPeriod": "PT24H"}
Defensive patterns

Strategy: validation

Validate before calling

if (!intervals.stream().anyMatch(i -> i.contains(row.getTimestamp()))) { dropOrRoute(row); }

Try / catch

try { allocator.allocate(row, seq, prevId, false); } catch (ISE e) { if (e.getMessage().startsWith("Could not find interval")) { logAndSkip(e, row); } else { throw e; } }

Prevention

When it happens

Trigger: Ingesting (or replaying) a row whose timestamp is outside the intervals enumerated in intervalToVersion — typically a late-arriving row older than the task's covered window, or a future-dated row.

Common situations: Re-running/replaying an ingestion task for a fixed interval with source data containing rows outside that interval; late data beyond the configured windowPeriod; clock-skewed producer emitting future timestamps; missing shardSpecs for the row's interval.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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