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

  1. Serialize the underlying BaseFileScanTask (e.g. task.asFileScanTask() or the wrapped delegate) instead of the custom wrapper
  2. Extend BaseFileScanTask or BaseFileScanTask.SplitScanTask so the instanceof checks recognize your implementation
  3. 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

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


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