apache/iceberg · error · UnsupportedOperationException
Unsupported task type:
Error message
Unsupported task type:
What it means
ScanTaskParser.toJson(FileScanTask, JsonGenerator) only knows how to serialize a fixed set of FileScanTask implementations: StaticDataTask, BaseFilesTable.ManifestReadTask, AllManifestsTable.ManifestListReadTask, BaseEntriesTable.ManifestReadTask, and BaseFileScanTask (including SplitScanTask). Any other FileScanTask implementation hits the else branch and throws this UnsupportedOperationException naming the class. It exists because serialization is type-dispatched and custom/unknown implementations have no JSON representation.
Source
Thrown at core/src/main/java/org/apache/iceberg/ScanTaskParser.java:102
generator.writeStringField(TASK_TYPE, TaskType.DATA_TASK.typeName());
DataTaskParser.toJson((StaticDataTask) fileScanTask, generator);
} else if (fileScanTask instanceof BaseFilesTable.ManifestReadTask) {
generator.writeStringField(TASK_TYPE, TaskType.FILES_TABLE_TASK.typeName());
FilesTableTaskParser.toJson((BaseFilesTable.ManifestReadTask) fileScanTask, generator);
} else if (fileScanTask instanceof AllManifestsTable.ManifestListReadTask) {
generator.writeStringField(TASK_TYPE, TaskType.ALL_MANIFESTS_TABLE_TASK.typeName());
AllManifestsTableTaskParser.toJson(
(AllManifestsTable.ManifestListReadTask) fileScanTask, generator);
} else if (fileScanTask instanceof BaseEntriesTable.ManifestReadTask) {
generator.writeStringField(TASK_TYPE, TaskType.MANIFEST_ENTRIES_TABLE_TASK.typeName());
ManifestEntriesTableTaskParser.toJson(
(BaseEntriesTable.ManifestReadTask) fileScanTask, generator);
} else if (fileScanTask instanceof BaseFileScanTask
|| fileScanTask instanceof BaseFileScanTask.SplitScanTask) {
generator.writeStringField(TASK_TYPE, TaskType.FILE_SCAN_TASK.typeName());
FileScanTaskParser.toJson(fileScanTask, generator);
} else {
throw new UnsupportedOperationException(
"Unsupported task type: " + fileScanTask.getClass().getCanonicalName());
}
generator.writeEndObject();
}
private static FileScanTask fromJson(JsonNode jsonNode, boolean caseSensitive) {
TaskType taskType = TaskType.FILE_SCAN_TASK;
String taskTypeStr = JsonUtil.getStringOrNull(TASK_TYPE, jsonNode);
if (null != taskTypeStr) {
taskType = TaskType.fromTypeName(taskTypeStr);
}
switch (taskType) {
case FILE_SCAN_TASK:
return FileScanTaskParser.fromJson(jsonNode, caseSensitive);
case DATA_TASK:
return DataTaskParser.fromJson(jsonNode);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Serialize the underlying BaseFileScanTask (e.g. task.asFileScanTask() or the wrapped delegate) instead of the custom wrapper
- Extend BaseFileScanTask or BaseFileScanTask.SplitScanTask so the instanceof checks recognize your implementation
- Upgrade Iceberg so the parser recognizes the task class, or add explicit serialization handling in your own code
Example fix
// before ScanTaskParser.toJson(new MyCustomFileScanTask(delegate)); // after ScanTaskParser.toJson(delegate); // serialize the BaseFileScanTask, not the wrapper
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(task instanceof StaticDataTask || task instanceof BaseFilesTable.ManifestReadTask || task instanceof AllManifestsTable.ManifestListReadTask || task instanceof BaseEntriesTable.ManifestReadTask || task instanceof BaseFileScanTask)) {
throw new IllegalArgumentException("Task type not serializable by ScanTaskParser: " + task.getClass().getName());
} Type guard
static boolean isSerializableScanTask(FileScanTask t) {
return t instanceof StaticDataTask || t instanceof BaseFileScanTask || t instanceof BaseFileScanTask.SplitScanTask
|| t instanceof BaseFilesTable.ManifestReadTask || t instanceof AllManifestsTable.ManifestListReadTask || t instanceof BaseEntriesTable.ManifestReadTask;
} Try / catch
try {
return ScanTaskParser.toJson(task);
} catch (UnsupportedOperationException e) {
throw new IllegalStateException("Cannot serialize custom scan task " + task.getClass().getName() + "; serialize its BaseFileScanTask delegate instead", e);
} Prevention
- Extend BaseFileScanTask or SplitScanTask for custom tasks so the parser recognizes them
- Unwrap decorators/wrappers before serializing
- Do not pass tasks from newer Iceberg versions into an older runtime's parser
When it happens
Trigger: Calling ScanTaskParser.toJson(task) with a custom FileScanTask implementation, a subclass that does not extend BaseFileScanTask, or a task type introduced in a newer Iceberg release that this parser does not recognize.
Common situations: Custom scan task implementations in downstream projects passed to the parser; mixed-version clusters where a task class from a newer Iceberg reaches an older serializer; wrapping/decorating FileScanTask objects and then serializing the wrapper.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot write unknown type:
- Type: %s is not supported
- Failed to write json for: %s
- Cannot convert update requirement to json. Unrecognized type
- Unrecognized update requirement. Cannot convert to json: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/e39523ae73ea2919.
Report an issue: GitHub.