{"record":{"id":"ecab2bf66d6de6d2","repo":"apache/druid","slug":"unexpected-state-two-versions-s-s-for-the","errorCode":null,"errorMessage":"Unexpected state: Two versions([%s], [%s]) for the same interval[%s]","messagePattern":"Unexpected state: Two versions\\(\\[(.+?)\\], \\[(.+?)\\]\\) for the same interval\\[(.+?)\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/PartialSegmentMergeTask.java","lineNumber":160,"sourceCode":"    // Group partitionLocations by interval and partitionId\n    final Map<Interval, Int2ObjectMap<List<PartitionLocation>>> intervalToBuckets = new HashMap<>();\n    for (PartitionLocation location : ioConfig.getPartitionLocations()) {\n      intervalToBuckets.computeIfAbsent(location.getInterval(), k -> new Int2ObjectOpenHashMap<>())\n                       .computeIfAbsent(location.getBucketId(), k -> new ArrayList<>())\n                       .add(location);\n    }\n\n    final List<TaskLock> locks = toolbox.getTaskActionClient().submit(\n        new SurrogateAction<>(getSupervisorTaskId(), new LockListAction())\n    );\n    final Map<Interval, String> intervalToVersion = Maps.newHashMapWithExpectedSize(locks.size());\n    locks.forEach(lock -> {\n      if (lock.isRevoked()) {\n        throw new ISE(\"Lock[%s] is revoked\", lock);\n      }\n      final String mustBeNull = intervalToVersion.put(lock.getInterval(), lock.getVersion());\n      if (mustBeNull != null) {\n        throw new ISE(\n            \"Unexpected state: Two versions([%s], [%s]) for the same interval[%s]\",\n            lock.getVersion(),\n            mustBeNull,\n            lock.getInterval()\n        );\n      }\n    });\n\n    final Stopwatch fetchStopwatch = Stopwatch.createStarted();\n    final Map<Interval, Int2ObjectMap<List<File>>> intervalToUnzippedFiles = fetchSegmentFiles(\n        toolbox,\n        intervalToBuckets\n    );\n    final long fetchTime = fetchStopwatch.elapsed(TimeUnit.SECONDS);\n    fetchStopwatch.stop();\n    LOG.info(\"Fetch took [%s] seconds\", fetchTime);\n\n    final ParallelIndexSupervisorTaskClient taskClient = toolbox.getSupervisorTaskClientProvider().build(","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/PartialSegmentMergeTask.java#L142-L178","documentation":"While listing the supervisor task's locks, PartialSegmentMergeTask expects at most one lock version per interval. If LockListAction returns two locks with different versions for the same interval, the lock state is inconsistent and the task throws this ISE.","triggerScenarios":"The task action server returns multiple locks for a single interval - typically after version upgrade/downgrade path bugs, corrupted task lock bookkeeping in the metadata store, or overlapping lock upgrades (e.g. replace-locks + timeChunk locks) for the supervisor task.","commonSituations":"Running tasks that requested both segment-granularity and chunk-granularity locks for the same interval; Druid version upgrades with lingering lock rows; manual edits or corruption of the druid_tasks/task lock tables.","solutions":["Kill all tasks holding locks on the affected interval and rerun the ingestion.","Inspect task lock entries in the metadata store for the interval and remove stale/duplicate lock rows if safe (during downtime).","Check whether any recent Druid upgrade left incompatible lock formats; consult upgrade notes.","Avoid submitting tasks with conflicting lock types (forceTimeChunkLock vs segment locks) on the same interval concurrently."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (IllegalStateException e) { if (e.getMessage().contains(\"Two versions\") && e.getMessage().contains(\"for the same interval\")) { /* kill tasks on the interval, clean lock state, rerun */ } else { throw e; } }","preventionTips":["Use a consistent lock strategy (e.g. forceTimeChunkLock) across tasks targeting the same interval.","Kill stale tasks holding locks before starting new ingestion on the same interval.","Watch for lock-table corruption after Druid upgrades or metadata store incidents."],"tags":["druid","task-locks","internal-state","batch-ingestion"],"backgroundTag":"internal-invariant-violation","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"}