{"record":{"id":"cdc669ec9771fde8","repo":"apache/druid","slug":"can-t-find-lock-for-the-interval-of-segment-s","errorCode":null,"errorMessage":"Can't find lock for the interval of segment[%s]","messagePattern":"Can't find lock for the interval of segment\\[(.+?)\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/common/actions/TaskLocks.java","lineNumber":281,"sourceCode":"    return segmentToReplaceLock;\n  }\n\n  public static List<TaskLock> findLocksForSegments(\n      final Task task,\n      final GlobalTaskLockbox taskLockbox,\n      final Collection<DataSegment> segments\n  )\n  {\n    final NavigableMap<DateTime, List<TaskLock>> taskLockMap = getTaskLockMap(taskLockbox, task);\n    if (taskLockMap.isEmpty()) {\n      return Collections.emptyList();\n    }\n\n    final List<TaskLock> found = new ArrayList<>();\n    segments.forEach(segment -> {\n      final Entry<DateTime, List<TaskLock>> entry = taskLockMap.floorEntry(segment.getInterval().getStart());\n      if (entry == null) {\n        throw new ISE(\"Can't find lock for the interval of segment[%s]\", segment.getId());\n      }\n\n      final List<TaskLock> locks = entry.getValue();\n      locks.forEach(lock -> {\n        if (lock.getGranularity() == LockGranularity.TIME_CHUNK) {\n          final TimeChunkLock timeChunkLock = (TimeChunkLock) lock;\n          if (timeChunkLock.getInterval().contains(segment.getInterval())\n              && timeChunkLock.getDataSource().equals(segment.getDataSource())\n              && timeChunkLock.getVersion().compareTo(segment.getVersion()) >= 0) {\n            found.add(lock);\n          }\n        } else {\n          final SegmentLock segmentLock = (SegmentLock) lock;\n          if (segmentLock.getInterval().contains(segment.getInterval())\n              && segmentLock.getDataSource().equals(segment.getDataSource())\n              && segmentLock.getVersion().compareTo(segment.getVersion()) >= 0\n              && segmentLock.getPartitionId() == segment.getShardSpec().getPartitionNum()) {\n            found.add(lock);","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/common/actions/TaskLocks.java#L263-L299","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nGrantrySpec with explicit intervals: 2024-01-01/2024-01-02\nbut segment interval: 2024-01-05/2024-01-06\n// after\nalign granularitySpec.query/intervals to include 2024-01-05/2024-01-06, or set segmentGranularity so each segment starts inside a locked interval","handlingStrategy":"validation","validationCode":"// ensure every segment interval starts within one of the task's locked intervals before processing\nfor (SegmentId seg : segments) {\n  boolean covered = locks.stream().anyMatch(l -> !l.getInterval().contains(seg.getInterval().getStart()) ? false : true);\n  if (!covered) throw new IllegalArgumentException(\"No lock covers segment \" + seg);\n}","typeGuard":null,"tryCatchPattern":"try {\n  taskLocks.findLocksForSegments(taskId, segments);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"Can't find lock for the interval of segment\")) {\n    // re-acquire locks or widen granularitySpec intervals, then retry\n  } else throw e;\n}","preventionTips":["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."],"tags":["indexing-service","task-locks","segments"],"backgroundTag":"resource-not-found","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}