apache/iceberg · error · UnsupportedOperationException

Columnar reads are not supported

Error message

Columnar reads are not supported

What it means

SparkRowReaderFactory explicitly does not support columnar reads: createColumnarReader() always throws UnsupportedOperationException('Columnar reads are not supported'), and supportColumnarReads() returns false. This factory exists solely for row-based reads (changelog/position-deletes).

Source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/source/SparkRowReaderFactory.java:61

    if (partition.allTasksOfType(FileScanTask.class)) {
      return new RowDataReader(partition);

    } else if (partition.allTasksOfType(ChangelogScanTask.class)) {
      return new ChangelogRowReader(partition);

    } else if (partition.allTasksOfType(PositionDeletesScanTask.class)) {
      return new PositionDeletesRowReader(partition);

    } else {
      throw new UnsupportedOperationException(
          "Unsupported task group for row-based reads: " + partition.taskGroup());
    }
  }

  @Override
  public PartitionReader<ColumnarBatch> createColumnarReader(InputPartition inputPartition) {
    throw new UnsupportedOperationException("Columnar reads are not supported");
  }

  @Override
  public boolean supportColumnarReads(InputPartition inputPartition) {
    return false;
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Ensure supportColumnarReads() returns false for scans using this factory so Spark never requests columnar readers
  2. Do not force columnar batch options on changelog/position-delete scans
  3. Use the standard SparkTable/SparkBatchQueryScan path which selects the correct reader factory
  4. If you need columnar reads, use the regular batch scan factory instead of the row reader factory

Example fix

// before
@Override
public boolean supportColumnarReads(InputPartition p) { return true; } // leads to throw
// after
@Override
public boolean supportColumnarReads(InputPartition p) { return false; }
Defensive patterns

Strategy: type-guard

Validate before calling

if (factory.supportColumnarReads(partition)) { reader = factory.createColumnarReader(partition); } else { reader = factory.createReader(partition); }

Type guard

boolean supportsColumnar = (factory instanceof SparkRowReaderFactory) ? false : factory.supportColumnarReads(partition);

Try / catch

try { return factory.createColumnarReader(p); } catch (UnsupportedOperationException e) { return factory.createReader(p); }

Prevention

When it happens

Trigger: Spark's DataSource V2 batch engine calls createColumnarReader because supportColumnarReads returned true or columnar read options were forced (e.g. spark.sql.sources.v2.batch.scan.enabled with columnar batching, or a custom reader wrapping this factory).

Common situations: Custom scan implementations advertising columnar support but delegating to SparkRowReaderFactory; misconfigured batch read options requesting ColumnarBatch output for changelog/position-delete reads.

Related errors


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