{"record":{"id":"64b3bca7b3f991b6","repo":"apache/druid","slug":"lock-interval-s-task-interval-s","errorCode":null,"errorMessage":"Lock interval[%s] != task interval[%s]","messagePattern":"Lock interval\\[(.+?)\\] != task interval\\[(.+?)\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/common/task/AbstractFixedIntervalTask.java","lineNumber":115,"sourceCode":"    return interval;\n  }\n\n  @Override\n  public void stopGracefully(TaskConfig taskConfig)\n  {\n  }\n\n  TaskLock getAndCheckLock(TaskToolbox toolbox) throws IOException\n  {\n    // Confirm we have a lock (will throw if there isn't exactly one element)\n    final TaskLock myLock = Iterables.getOnlyElement(getTaskLocks(toolbox.getTaskActionClient()));\n\n    if (!myLock.getDataSource().equals(getDataSource())) {\n      throw new ISE(\"Lock dataSource[%s] != task dataSource[%s]\", myLock.getDataSource(), getDataSource());\n    }\n\n    if (!myLock.getInterval().equals(getInterval())) {\n      throw new ISE(\"Lock interval[%s] != task interval[%s]\", myLock.getInterval(), getInterval());\n    }\n    return myLock;\n  }\n}\n","sourceCodeStart":97,"sourceCodeEnd":120,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/common/task/AbstractFixedIntervalTask.java#L97-L120","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nTaskLock lock = taskActionClient.submit(new LockTryAcquireAction(new TaskLock(\"ds\", new Interval(\"2023/2024\"), \"p\")));\n// task configured with Interval(\"2023-01-01/2024-01-01\") mismatch\n// after\nInterval taskInterval = getInterval();\nTaskLock lock = taskActionClient.submit(new LockTryAcquireAction(new TaskLock(\"ds\", taskInterval, \"p\")));","handlingStrategy":"validation","validationCode":"if (!lock.getInterval().equals(task.getInterval())) { throw new IllegalStateException(\"lock/task interval mismatch, re-submit task\"); }","typeGuard":null,"tryCatchPattern":"try { lock = task.getAndCheckLock(taskActionClient); } catch (IllegalStateException e) { if (e.getMessage().contains(\"Lock interval\")) { /* resubmit task / reacquire lock */ } else throw e; }","preventionTips":["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."],"tags":["druid","indexing","locking","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}