{"record":{"id":"f3528ce1eb9b3566","repo":"apache/druid","slug":"task-datasource-must-match-action-datasource-s","errorCode":null,"errorMessage":"Task dataSource must match action dataSource, [%s] != [%s].","messagePattern":"Task dataSource must match action dataSource, \\[(.+?)\\] != \\[(.+?)\\]\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/common/actions/SegmentAllocateAction.java","lineNumber":224,"sourceCode":"\n  @Override\n  public SegmentIdWithShardSpec perform(\n      final Task task,\n      final TaskActionToolbox toolbox\n  )\n  {\n    if (!(task instanceof PendingSegmentAllocatingTask)) {\n      throw DruidException.defensive(\n          \"Task[%s] of type[%s] cannot allocate segments as it does not implement PendingSegmentAllocatingTask.\",\n          task.getId(), task.getType()\n      );\n    }\n    int attempt = 0;\n    while (true) {\n      attempt++;\n\n      if (!task.getDataSource().equals(dataSource)) {\n        throw new IAE(\"Task dataSource must match action dataSource, [%s] != [%s].\", task.getDataSource(), dataSource);\n      }\n\n      final IndexerMetadataStorageCoordinator msc = toolbox.getIndexerMetadataStorageCoordinator();\n\n      // 1) if something overlaps our timestamp, use that\n      // 2) otherwise try preferredSegmentGranularity & going progressively smaller\n\n      final Interval rowInterval = queryGranularity.bucket(timestamp).withChronology(ISOChronology.getInstanceUTC());\n\n      final Set<DataSegment> usedSegmentsForRow =\n          new HashSet<>(msc.retrieveUsedSegmentsForInterval(dataSource, rowInterval, Segments.ONLY_VISIBLE));\n\n      final SegmentIdWithShardSpec identifier;\n      if (usedSegmentsForRow.isEmpty()) {\n        identifier = tryAllocateFirstSegment(toolbox, task, rowInterval);\n      } else {\n        identifier = tryAllocateSubsequentSegment(toolbox, task, rowInterval, usedSegmentsForRow.iterator().next());\n      }","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/common/actions/SegmentAllocateAction.java#L206-L242","documentation":"SegmentAllocateAction.perform() enforces that the Task executing this action is allocating a segment for its own datasource. The task's dataSource must equal the action's dataSource field; any mismatch is rejected with this IAE before touching the metadata store. This guards against a task obtaining or poisoning segment lineage for another datasource.","triggerScenarios":"A task action payload was deserialized with a dataSource different from the task's actual dataSource (hand-crafted or stale task payloads), or custom task code copies a SegmentAllocateAction from another task/context.","commonSituations":"Manually resubmitting or editing task JSON where the spec dataSource was renamed but the stored action was not; building custom ingestion tasks that reuse an allocate action across specs; replaying old task checkpoints after a datasource rename.","solutions":["Ensure the datasource in the ingestion spec matches the one in every segment-allocate action; regenerate the task instead of editing its payload.","Resubmit the task/supervisor with a consistent dataSource name.","If renaming a datasource, restart the supervisor/task from scratch rather than reusing old task state.","Check custom task code so SegmentAllocateAction is always constructed with the task's own getDataSource()."],"exampleFix":"// before\nSegmentAllocateAction action = new SegmentAllocateAction(\"old-datasource\", ...); // in task for \"new-datasource\"\n// after\nSegmentAllocateAction action = new SegmentAllocateAction(task.getDataSource(), ...);","handlingStrategy":"validation","validationCode":"if (!task.getDataSource().equals(actionDataSource)) {\n  throw new IllegalArgumentException(\"dataSource mismatch: task=\" + task.getDataSource() + \" action=\" + actionDataSource);\n}","typeGuard":null,"tryCatchPattern":"try { result = action.perform(task, toolbox); } catch (IAE e) { if (e.getMessage().startsWith(\"Task dataSource must match\")) { /* resubmit task with consistent datasource */ } else throw e; }","preventionTips":["Never hand-edit task JSON payloads; resubmit from the original spec.","Construct SegmentAllocateAction from task.getDataSource() in custom tasks.","Regenerate tasks after datasource renames.","Validate spec datasource in CI for custom task code."],"tags":["druid","segment-allocation","datasource-mismatch","task-action"],"backgroundTag":"invalid-argument-value","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"}