apache/druid · error · IllegalStateException

Lock[%s] is revoked

Error message

Lock[%s] is revoked

What it means

PartialSegmentMergeTask runs under a surrogate lock taken on behalf of its supervisor task. At startup it lists the supervisor's locks via SurrogateAction(LockListAction); if any listed lock has been revoked (e.g. lost due to a segment being published by another task or lock timeout), the task aborts immediately with this ISE.

Source

Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/PartialSegmentMergeTask.java:156

  @Override
  public TaskStatus runTask(TaskToolbox toolbox) throws Exception
  {
    // Group partitionLocations by interval and partitionId
    final Map<Interval, Int2ObjectMap<List<PartitionLocation>>> intervalToBuckets = new HashMap<>();
    for (PartitionLocation location : ioConfig.getPartitionLocations()) {
      intervalToBuckets.computeIfAbsent(location.getInterval(), k -> new Int2ObjectOpenHashMap<>())
                       .computeIfAbsent(location.getBucketId(), k -> new ArrayList<>())
                       .add(location);
    }

    final List<TaskLock> locks = toolbox.getTaskActionClient().submit(
        new SurrogateAction<>(getSupervisorTaskId(), new LockListAction())
    );
    final Map<Interval, String> intervalToVersion = Maps.newHashMapWithExpectedSize(locks.size());
    locks.forEach(lock -> {
      if (lock.isRevoked()) {
        throw new ISE("Lock[%s] is revoked", lock);
      }
      final String mustBeNull = intervalToVersion.put(lock.getInterval(), lock.getVersion());
      if (mustBeNull != null) {
        throw new ISE(
            "Unexpected state: Two versions([%s], [%s]) for the same interval[%s]",
            lock.getVersion(),
            mustBeNull,
            lock.getInterval()
        );
      }
    });

    final Stopwatch fetchStopwatch = Stopwatch.createStarted();
    final Map<Interval, Int2ObjectMap<List<File>>> intervalToUnzippedFiles = fetchSegmentFiles(
        toolbox,
        intervalToBuckets
    );
    final long fetchTime = fetchStopwatch.elapsed(TimeUnit.SECONDS);

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Rerun the supervisor batch task so it acquires fresh locks before spawning partial merge tasks.
  2. Check for other ingestion/compaction tasks competing for the same intervals and stagger them.
  3. Review Overlord logs around lock revocation to see which task stole or revoked the lock.
  4. Verify task lock configuration (lock timeout, force-time-chunk-lock) matches the workload.
Defensive patterns

Strategy: retry

Try / catch

catch (IllegalStateException e) { if (e.getMessage().matches(".*Lock\[.*\] is revoked.*")) { /* rerun supervisor to reacquire locks */ } else { throw e; } }

Prevention

When it happens

Trigger: The timeChunk/time interval lock held by the supervisor parallel task was revoked before or during the partial merge task run - commonly because the lock's interval was superseded by another task or the lock request version was overwritten.

Common situations: Concurrent ingestion or compaction targeting overlapping intervals; supervisor task retry after its locks were reassigned; slow merge tasks outliving their lock validity; metadata store failover issues.

Related errors


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