apache/druid · error · IllegalStateException

Can't find lock for the interval of segment[%s]

Error message

Can't find lock for the interval of segment[%s]

What it means

TaskLocks.findLocksForSegments maps each segment to the task locks covering its interval, using a floor lookup on a time-sorted lock map. If no lock entry exists at or before the segment's start time, Druid cannot verify which lock authorized the segment, so it throws. This guards the invariant that every segment being written must be covered by an active task lock.

Source

Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/actions/TaskLocks.java:281

    return segmentToReplaceLock;
  }

  public static List<TaskLock> findLocksForSegments(
      final Task task,
      final GlobalTaskLockbox taskLockbox,
      final Collection<DataSegment> segments
  )
  {
    final NavigableMap<DateTime, List<TaskLock>> taskLockMap = getTaskLockMap(taskLockbox, task);
    if (taskLockMap.isEmpty()) {
      return Collections.emptyList();
    }

    final List<TaskLock> found = new ArrayList<>();
    segments.forEach(segment -> {
      final Entry<DateTime, List<TaskLock>> entry = taskLockMap.floorEntry(segment.getInterval().getStart());
      if (entry == null) {
        throw new ISE("Can't find lock for the interval of segment[%s]", segment.getId());
      }

      final List<TaskLock> locks = entry.getValue();
      locks.forEach(lock -> {
        if (lock.getGranularity() == LockGranularity.TIME_CHUNK) {
          final TimeChunkLock timeChunkLock = (TimeChunkLock) lock;
          if (timeChunkLock.getInterval().contains(segment.getInterval())
              && timeChunkLock.getDataSource().equals(segment.getDataSource())
              && timeChunkLock.getVersion().compareTo(segment.getVersion()) >= 0) {
            found.add(lock);
          }
        } else {
          final SegmentLock segmentLock = (SegmentLock) lock;
          if (segmentLock.getInterval().contains(segment.getInterval())
              && segmentLock.getDataSource().equals(segment.getDataSource())
              && segmentLock.getVersion().compareTo(segment.getVersion()) >= 0
              && segmentLock.getPartitionId() == segment.getShardSpec().getPartitionNum()) {
            found.add(lock);

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Verify the task's granularitySpec interval/segmentGranularity covers every segment being processed; adjust intervals or segment granularity so segment start times fall within locked ranges.
  2. Re-acquire locks: check /druid/indexer/v1/task/{id}/status and lock state; restart the task so it acquires locks up front.
  3. Check for lock revocation in overlord logs (higher-priority tasks stealing locks) and resolve the competing task or run sequentially.
  4. Ensure the segments passed belong to the same datasource and time ranges the task locked.

Example fix

// before
GrantrySpec with explicit intervals: 2024-01-01/2024-01-02
but segment interval: 2024-01-05/2024-01-06
// after
align granularitySpec.query/intervals to include 2024-01-05/2024-01-06, or set segmentGranularity so each segment starts inside a locked interval
Defensive patterns

Strategy: validation

Validate before calling

// ensure every segment interval starts within one of the task's locked intervals before processing
for (SegmentId seg : segments) {
  boolean covered = locks.stream().anyMatch(l -> !l.getInterval().contains(seg.getInterval().getStart()) ? false : true);
  if (!covered) throw new IllegalArgumentException("No lock covers segment " + seg);
}

Try / catch

try {
  taskLocks.findLocksForSegments(taskId, segments);
} catch (IllegalStateException e) {
  if (e.getMessage().contains("Can't find lock for the interval of segment")) {
    // re-acquire locks or widen granularitySpec intervals, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Calling an action that validates locks for segments (e.g. segment allocate/commit-style flows) when the task's lock map has no entry whose interval starts at or before the segment interval — typically because locks were revoked, released, or never acquired for the segment's time range.

Common situations: Segment timestamps outside the task's locked intervals (misconfigured granularitySpec intervals or segment granularity); locks revoked due to overlord restart or version conflicts; using segments from a different datasource/period than the locked one.

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/cdc669ec9771fde8. Report an issue: GitHub.