apache/druid · error · IllegalStateException
Lock revoked: [%s]
Error message
Lock revoked: [%s]
What it means
findIntervalAndVersion lists the task's current locks every time it allocates a new segment, because locks may have been revoked since acquisition. If any listed lock is revoked, the task can no longer safely allocate segments under it and throws this ISE. It surfaces that a higher-priority task took over the lock and this task must stop writing.
Source
Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/AbstractBatchIndexTask.java:813
TaskToolbox toolbox,
IngestionSpec<?, ?> ingestionSpec,
DateTime timestamp,
TaskLockType taskLockType
) throws IOException
{
// This method is called whenever subtasks need to allocate a new segment via the supervisor task.
// As a result, this code is never called in the Overlord. For now using the materialized intervals
// here is ok for performance reasons
GranularitySpec granularitySpec = ingestionSpec.getDataSchema().getGranularitySpec();
final Set<Interval> materializedBucketIntervals = granularitySpec.materializedBucketIntervals();
// List locks whenever allocating a new segment because locks might be revoked and no longer valid.
final List<TaskLock> locks = toolbox
.getTaskActionClient()
.submit(new LockListAction());
final TaskLock revokedLock = locks.stream().filter(TaskLock::isRevoked).findAny().orElse(null);
if (revokedLock != null) {
throw new ISE("Lock revoked: [%s]", revokedLock);
}
final Map<Interval, String> versions = locks.stream().collect(
Collectors.toMap(TaskLock::getInterval, TaskLock::getVersion)
);
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);View on GitHub (pinned to 9b90983fd2)
Solutions
- Let the task fail and retry later once the higher-priority/competing task has finished; the revoked lock cannot be recovered mid-run.
- Check overlord logs for which task stole the lock; re-prioritize tasks (set higher priority for your ingestion or pause compaction) to avoid overlap.
- Resubmit the task after the conflict resolves; it will re-acquire fresh locks.
- Avoid running two writers for the same datasource/interval concurrently.
Defensive patterns
Strategy: try-catch
Try / catch
try {
allocateSegment(...);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Lock revoked:")) {
// stop writing; wait for the competing task to complete, then resubmit this task
} else throw e;
} Prevention
- Avoid running ingestion and compaction over the same intervals simultaneously.
- Assign higher priority to tasks that must not lose their locks.
- Monitor overlord logs for lock-revocation events and alert on them.
When it happens
Trigger: Allocating a segment via SegmentAllocAction-style flow after another task with higher priority (or a manual lock revoke) caused this task's lock to be revoked; typical during concurrent compaction vs. ingestion or task priority changes.
Common situations: Running an ingestion task while a compaction job or higher-priority supervisor takes over the interval; operator manually revoking locks; overlord lock management during failover.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Cannot start; not ready!
- Number of locks exceeded maxAllowedLockCount [%s].
- Cannot find a version for interval[%s]
- Lock dataSource[%s] != task dataSource[%s]
- Can't find surrogate task[%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/c35203e44594c7bc.
Report an issue: GitHub.