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
- 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.
- Re-acquire locks: check /druid/indexer/v1/task/{id}/status and lock state; restart the task so it acquires locks up front.
- Check for lock revocation in overlord logs (higher-priority tasks stealing locks) and resolve the competing task or run sequentially.
- 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
- Keep granularitySpec intervals aligned with segmentGranularity and covering all data.
- Avoid concurrent tasks on the same datasource/interval that could revoke your locks.
- Verify segment timestamps match the ingestion time window before submitting.
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
- Cannot find a version for interval[%s]
- Failed to get s3 object for bucket[%s], key[%s], range[bytes
- Can't find surrogate task[%s]
- Cannot start; not ready!
- Number of locks exceeded maxAllowedLockCount [%s].
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/cdc669ec9771fde8.
Report an issue: GitHub.