apache/druid · error · IllegalStateException

Cannot find a version for interval[%s]

Error message

Cannot find a version for interval[%s]

What it means

After determining the interval for a timestamp, findIntervalAndVersion looks up the lock version associated with that interval from the task's listed locks via findVersion. If no lock covers the interval (version is null) in the explicit-intervals path — where locks should already have been acquired at task startup — this ISE is thrown. It means the task is allocating a segment in an interval it never locked.

Source

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

    final Interval interval;
    final String version;
    if (!materializedBucketIntervals.isEmpty()) {
      // If granularity spec has explicit intervals, we just need to find the version associated to the interval.
      // This is because we should have gotten all required locks up front when the task starts up.
      final Optional<Interval> maybeInterval = granularitySpec.bucketInterval(timestamp);
      if (!maybeInterval.isPresent()) {
        throw new IAE("Could not find interval for timestamp [%s]", timestamp);
      }

      interval = maybeInterval.get();
      if (!materializedBucketIntervals.contains(interval)) {
        throw new ISE("Unspecified interval[%s] in granularitySpec[%s]", interval, granularitySpec);
      }

      version = AbstractBatchIndexTask.findVersion(versions, interval);
      if (version == null) {
        throw new ISE("Cannot find a version for interval[%s]", interval);
      }
    } else {
      // We don't have explicit intervals. We can use the segment granularity to figure out what
      // interval we need, but we might not have already locked it.
      interval = granularitySpec.getSegmentGranularity().bucket(timestamp);
      final String existingLockVersion = AbstractBatchIndexTask.findVersion(versions, interval);
      if (existingLockVersion == null) {
        if (ingestionSpec.getTuningConfig() instanceof ParallelIndexTuningConfig) {
          final int maxAllowedLockCount = ((ParallelIndexTuningConfig) ingestionSpec.getTuningConfig())
              .getMaxAllowedLockCount();
          if (maxAllowedLockCount >= 0 && locks.size() >= maxAllowedLockCount) {
            throw new MaxAllowedLocksExceededException(maxAllowedLockCount);
          }
        }
        // We don't have a lock for this interval, so we should lock it now.
        final TaskLock lock = Preconditions.checkNotNull(
            toolbox.getTaskActionClient().submit(
                new TimeChunkLockTryAcquireAction(taskLockType, interval)

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Restart/resubmit the task so it re-acquires locks for all explicit intervals at startup.
  2. Check overlord logs for lock revocation and resolve the competing task before rerunning.
  3. Verify no other task is ingesting the same datasource/interval concurrently.
  4. If this recurs, investigate overlord task-storage/lock persistence issues after failovers.
Defensive patterns

Strategy: retry

Try / catch

try {
  ingest(records);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Cannot find a version for interval")) {
    // resubmit the task so locks are re-acquired at startup
  } else throw e;
}

Prevention

When it happens

Trigger: Explicit-interval ingestion where locks expected at startup were lost (revoked/expired) before segment allocation, so LockListAction returns no version for the record's interval.

Common situations: Locks revoked by a competing higher-priority task mid-run; overlord restart dropping lock state; task running far longer than expected while intervals were locked only at startup.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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