apache/iceberg · error · IllegalStateException
Unexpected ContentScanTask type: <task.getClass().getName()>
Error message
Unexpected ContentScanTask type: <task.getClass().getName()>
What it means
The reader operator received a ReadCommand whose scan task is of a ContentScanTask subtype it cannot process (neither a data-file task it recognizes nor an EqualityDeleteFileScanTask). This is an internal contract violation between the planner's emitted tasks and the reader's supported types. The operator logs the failure, emits to the error stream, and signals ABORT on READER_ABORT_STREAM.
Source
Thrown at flink/v1.20/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)
Solutions
- Align all Iceberg Flink maintenance classes to a single version - check the deployed jar for duplicates/multiple Iceberg versions on the classpath.
- Check the TaskResultAggregator error stream for the offending task class name and trace which operator emitted it.
- Ensure the planner only feeds supported tasks (data files and equality delete scan tasks) into the reader stream.
- If you added a new task type, extend EqualityConvertReader.processElement to handle it explicitly.
Example fix
// before: reader knows only DataFile/EqualityDelete tasks
// after: add explicit handling or reject early in the planner
if (!(task instanceof DataFileScanTask || task instanceof EqualityDeleteFileScanTask)) {
throw new IllegalStateException("Planner emitted unsupported task type: " + task.getClass());
} Defensive patterns
Strategy: type-guard
Validate before calling
// validate before pushing commands into the reader stream
checkState(task instanceof DataFileScanTask || task instanceof EqualityDeleteFileScanTask,
"Unsupported task type: " + task.getClass()); Type guard
boolean isReaderSupportedTask(ContentScanTask<?> task) {
return task instanceof DataFileScanTask || task instanceof EqualityDeleteFileScanTask;
} Try / catch
// reader already aborts via READER_ABORT_STREAM; monitor it
READER_ABORT_STREAM.process((ctx, abort) -> {
if (abort == DVPosition.ABORT) failJob("reader aborted: unsupported scan task");
}); Prevention
- Keep planner and reader classes from the same connector build.
- Do not add custom scan-task producers upstream of EqualityConvertReader.
- Watch the error/abort side streams in tests after upgrading Iceberg.
- Grep your classpath for multiple org.apache.iceberg versions.
When it happens
Trigger: A planner (or custom code feeding the reader input stream) emits a scan task type outside {DataFileScanTask-like, EqualityDeleteFileScanTask}, e.g. a position-delete scan task or a new task class introduced by an upgrade.
Common situations: Mixed Iceberg connector versions in the job jar; a V2 positional-delete task reaching the reader after misconfiguration; custom operators injecting tasks into the reader stream.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Unknown type for int field. Type name: ${className}
- Unknown type for long field. Type name: ${className}
- Unknown type for timestamp_ns: ${class}
- Unknown type for binary field. Type name: ${className}
- Unexpected object type for TIMESTAMP logical type. Received:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/e1c674bfe3a4d79a.
Report an issue: GitHub.