apache/iceberg · error · IllegalStateException

Unexpected ContentScanTask type:

Error message

Unexpected ContentScanTask type: 

What it means

The EqualityConvertReader dispatches each ReadCommand's ContentScanTask to a processor by concrete type (data file task, staging task, or EqualityDeleteFileScanTask). If a task of an unknown ContentScanTask subtype arrives, the reader throws IllegalStateException naming the class. The exception is caught, logged, and forwarded on the ERROR_STREAM and READER_ABORT_STREAM so the maintenance task fails cleanly.

Solutions

  1. Ensure the planner (EqualityConvertPlanner) and reader come from the same Iceberg/Flink build; do not restore from a savepoint taken with a different version.
  2. Log the task class name (included in the message) and add the corresponding instanceof branch or upgrade Iceberg to the version that supports that task type.
  3. Discard in-flight commands and re-trigger the maintenance cycle so the planner re-plans with current task types.
Defensive patterns

Strategy: type-guard

Validate before calling

// before submitting commands downstream
if (!(task instanceof IniCloseableIterable)) { /* see guard */ }
if (!(task instanceof DataFileScanTask || task instanceof EqualityDeleteFileScanTask)) {
  throw new IllegalArgumentException("Unsupported task type: " + task.getClass());
}

Type guard

static boolean isSupportedTask(ContentScanTask<?> task) {
  return task instanceof DataFileScanTask
      || task instanceof EqualityDeleteFileScanTask;
}

Try / catch

try {
  processElement(cmd, ctx, out);
} catch (IllegalStateException e) {
  LOG.error("Unsupported scan task {}; re-planning required", e.getMessage());
  ctx.output(TaskResultAggregator.ERROR_STREAM, e);
}

Prevention

When it happens

Trigger: processElement receives a ReadCommand whose scan task is neither an expected data-file scan task nor an EqualityDeleteFileScanTask — e.g. after an Iceberg/Flink version change introduces a new ContentScanTask implementation, or a command was serialized by a different planner version.

Common situations: Mixing maintenance job versions: a checkpoint/savepoint restored commands planned by an older or newer planner that emits a task type this reader does not know; custom scan task implementations injected upstream.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/47289162f72369ac. Report an issue: GitHub.

Appendix: source

Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/operator/EqualityConvertReader.java:126

  @Override
  public void processElement(ReadCommand cmd, Context ctx, Collector<IndexCommand> out)
      throws Exception {
    ContentScanTask<?> task = cmd.task();
    ContentFile<?> file = task.file();
    try {
      if (task instanceof FileScanTask dataTask) {
        processDataFile(
            dataTask,
            cmd.mainSnapshotId(),
            cmd.indexGeneration(),
            cmd.dataSequenceNumber(),
            cmd.staging(),
            out);
      } else if (task instanceof EqualityDeleteFileScanTask deleteTask) {
        processDeleteFile(
            deleteTask, cmd.mainSnapshotId(), cmd.indexGeneration(), cmd.dataSequenceNumber(), out);
      } else {
        throw new IllegalStateException(
            "Unexpected ContentScanTask type: " + task.getClass().getName());
      }
    } catch (Exception e) {
      LOG.error("Reader failed to process command for file={}", file.location(), e);
      ctx.output(TaskResultAggregator.ERROR_STREAM, e);
      ctx.output(READER_ABORT_STREAM, DVPosition.ABORT);
    }
  }

  private void processDataFile(
      FileScanTask task,
      Long mainSnapshotId,
      Long indexGeneration,
      long dataSequenceNumber,
      boolean staging,
      Collector<IndexCommand> out)
      throws IOException {
    ContentFile<?> file = task.file();

View on GitHub (pinned to 86d9c8fc54)