apache/druid · error · IllegalStateException
Lock interval[%s] != task interval[%s]
Error message
Lock interval[%s] != task interval[%s]
What it means
Thrown by AbstractFixedIntervalTask.getAndCheckLock when the lock the task actually holds does not match the task's declared interval. Druid tasks acquire a time-interval lock (via TaskActionClient) before writing; if the lock interval differs from getInterval(), the task's writes would fall outside the locked range, so Druid fails fast with an IllegalStateException to protect segment consistency.
Source
Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/AbstractFixedIntervalTask.java:115
return interval;
}
@Override
public void stopGracefully(TaskConfig taskConfig)
{
}
TaskLock getAndCheckLock(TaskToolbox toolbox) throws IOException
{
// Confirm we have a lock (will throw if there isn't exactly one element)
final TaskLock myLock = Iterables.getOnlyElement(getTaskLocks(toolbox.getTaskActionClient()));
if (!myLock.getDataSource().equals(getDataSource())) {
throw new ISE("Lock dataSource[%s] != task dataSource[%s]", myLock.getDataSource(), getDataSource());
}
if (!myLock.getInterval().equals(getInterval())) {
throw new ISE("Lock interval[%s] != task interval[%s]", myLock.getInterval(), getInterval());
}
return myLock;
}
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Verify the task's configured interval exactly matches the interval of the lock granted by the overlord (compare task JSON 'interval' with the lock in the tasks/locks UI).
- Recreate/respawn the task after any change to the datasource or interval so locks are re-acquired for the new interval.
- If using a custom task, ensure the TaskLock acquired in the run() path uses the same Interval object returned by getInterval().
- Check for interval normalization (e.g., granularity truncation) that changes the interval between lock request and lock check.
Example fix
// before
TaskLock lock = taskActionClient.submit(new LockTryAcquireAction(new TaskLock("ds", new Interval("2023/2024"), "p")));
// task configured with Interval("2023-01-01/2024-01-01") mismatch
// after
Interval taskInterval = getInterval();
TaskLock lock = taskActionClient.submit(new LockTryAcquireAction(new TaskLock("ds", taskInterval, "p"))); Defensive patterns
Strategy: validation
Validate before calling
if (!lock.getInterval().equals(task.getInterval())) { throw new IllegalStateException("lock/task interval mismatch, re-submit task"); } Try / catch
try { lock = task.getAndCheckLock(taskActionClient); } catch (IllegalStateException e) { if (e.getMessage().contains("Lock interval")) { /* resubmit task / reacquire lock */ } else throw e; } Prevention
- Always derive the lock interval from getInterval(), never hardcode intervals.
- Re-submit tasks after editing their spec rather than reusing stale locks.
- Compare task JSON interval vs granted lock in the overlord API before debugging deeper.
When it happens
Trigger: A task subclass (or a mocked/stubbed TaskLock) returns a lock whose Interval differs from the task's configured interval; typically when task interval is set programmatically, after interval truncation/alignment, or when a lock is reused/misconfigured in tests or custom task types.
Common situations: Custom ingestion/kill/archive tasks built on AbstractFixedIntervalTask where the datasource/interval passed to the constructor doesn't match what the overlord granted; clock or timezone confusion causing the requested interval to shift; restoring tasks or spec edits that changed ioConfig.interval between submit and run.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- The lock for interval[%s] is preempted and no longer valid
- Some locks for task[%s] are already revoked
- Some locks for task[%s] are already revoked
- Failed to get locks for intervals[%s]
- DynamicPartitionsSpec must be used for best-effort rollup
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/64b3bca7b3f991b6.
Report an issue: GitHub.