{"record":{"id":"4c2b59b7124ac2c6","repo":"apache/druid","slug":"unused-segment-s-has-version-s-task-version-4c2b59","errorCode":null,"errorMessage":"Unused segment[%s] has version[%s] > task version[%s]","messagePattern":"Unused segment\\[(.+?)\\] has version\\[(.+?)\\] > task version\\[(.+?)\\]","errorType":"exception","errorClass":"ISE","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/common/task/MoveTask.java","lineNumber":96,"sourceCode":"  public Set<ResourceAction> getInputSourceResources()\n  {\n    return ImmutableSet.of();\n  }\n\n  @Override\n  public TaskStatus runTask(TaskToolbox toolbox) throws Exception\n  {\n    final TaskLock myLock = getAndCheckLock(toolbox);\n\n    // List unused segments\n    final List<DataSegment> unusedSegments = toolbox\n        .getTaskActionClient()\n        .submit(new RetrieveUnusedSegmentsAction(myLock.getDataSource(), myLock.getInterval(), null, null, null));\n\n    // Verify none of these segments have versions > lock version\n    for (final DataSegment unusedSegment : unusedSegments) {\n      if (unusedSegment.getVersion().compareTo(myLock.getVersion()) > 0) {\n        throw new ISE(\n            \"Unused segment[%s] has version[%s] > task version[%s]\",\n            unusedSegment.getId(),\n            unusedSegment.getVersion(),\n            myLock.getVersion()\n        );\n      }\n\n      log.info(\"OK to move segment: %s\", unusedSegment.getId());\n    }\n\n    // Move segments\n    for (DataSegment segment : unusedSegments) {\n      final DataSegment movedSegment = toolbox.getDataSegmentMover().move(segment, targetLoadSpec);\n      toolbox.getTaskActionClient().submit(new SegmentMetadataUpdateAction(ImmutableSet.of(movedSegment)));\n    }\n\n    return TaskStatus.success(getId());\n  }","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/common/task/MoveTask.java#L78-L114","documentation":"MoveTask relocates segments between deep-storage locations, but it may only move segments whose version is <= the version of the task's lock (segments with newer versions must not be overwritten/moved by an older-generation task). If any retrieved unused segment has a higher version, the task aborts with ISE.","triggerScenarios":"A move task holding a lock with version V encounters an unused segment in the same interval whose version is newer than V — typically because a later replace/compaction task wrote segments with a new version into the same interval before the move ran.","commonSituations":"Submitting a move task while concurrent compaction has replaced segments with newer versions; stale move spec created before a re-ingestion; time-versioned segments after manual inserts or speculative retries.","solutions":["Re-submit the move task after the concurrent replace/compaction finishes so the lock acquires the latest version","Restrict the move interval to segments whose versions match the move task's lock version","Verify with metadata queries which segments have newer versions and either kill them first or align versions"],"exampleFix":"// before\n// move task created before a compaction ran\n// after\n// resubmit the move task; it acquires a new lock version covering the newer segments","handlingStrategy":"validation","validationCode":"List<DataSegment> unused = retrieveUnused(dataSource, interval);\nif (unused.stream().anyMatch(s -> s.getVersion().compareTo(lockVersion) > 0)) { throw new IllegalStateException(\"newer segments present; resubmit move later\"); }","typeGuard":null,"tryCatchPattern":"try { moveTask.runTask(actionClient); } catch (ISE e) { if (e.getMessage().contains(\"has version\")) { resubmitAfterCompaction(); } else { throw e; } }","preventionTips":["Don't schedule move tasks overlapping in time with compaction/replace","Recreate move specs after any re-ingestion of the interval","Query segment versions for the interval before moving"],"tags":["druid","move-task","locking","segments"],"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"}