{"record":{"id":"7986212070a4e922","repo":"apache/iceberg","slug":"columnar-reads-are-not-supported-798621","errorCode":null,"errorMessage":"Columnar reads are not supported","messagePattern":"Columnar reads are not supported","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/source/SparkRowReaderFactory.java","lineNumber":61,"sourceCode":"\n    if (partition.allTasksOfType(FileScanTask.class)) {\n      return new RowDataReader(partition);\n\n    } else if (partition.allTasksOfType(ChangelogScanTask.class)) {\n      return new ChangelogRowReader(partition);\n\n    } else if (partition.allTasksOfType(PositionDeletesScanTask.class)) {\n      return new PositionDeletesRowReader(partition);\n\n    } else {\n      throw new UnsupportedOperationException(\n          \"Unsupported task group for row-based reads: \" + partition.taskGroup());\n    }\n  }\n\n  @Override\n  public PartitionReader<ColumnarBatch> createColumnarReader(InputPartition inputPartition) {\n    throw new UnsupportedOperationException(\"Columnar reads are not supported\");\n  }\n\n  @Override\n  public boolean supportColumnarReads(InputPartition inputPartition) {\n    return false;\n  }\n}\n","sourceCodeStart":43,"sourceCodeEnd":69,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/source/SparkRowReaderFactory.java#L43-L69","documentation":"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).","triggerScenarios":"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).","commonSituations":"Custom scan implementations advertising columnar support but delegating to SparkRowReaderFactory; misconfigured batch read options requesting ColumnarBatch output for changelog/position-delete reads.","solutions":["Ensure supportColumnarReads() returns false for scans using this factory so Spark never requests columnar readers","Do not force columnar batch options on changelog/position-delete scans","Use the standard SparkTable/SparkBatchQueryScan path which selects the correct reader factory","If you need columnar reads, use the regular batch scan factory instead of the row reader factory"],"exampleFix":"// before\n@Override\npublic boolean supportColumnarReads(InputPartition p) { return true; } // leads to throw\n// after\n@Override\npublic boolean supportColumnarReads(InputPartition p) { return false; }","handlingStrategy":"type-guard","validationCode":"if (factory.supportColumnarReads(partition)) { reader = factory.createColumnarReader(partition); } else { reader = factory.createReader(partition); }","typeGuard":"boolean supportsColumnar = (factory instanceof SparkRowReaderFactory) ? false : factory.supportColumnarReads(partition);","tryCatchPattern":"try { return factory.createColumnarReader(p); } catch (UnsupportedOperationException e) { return factory.createReader(p); }","preventionTips":["Never advertise supportColumnarReads=true for factories that only produce rows","Don't force columnar batch options on changelog/position-delete scans","Use the standard batch scan path for columnar reads"],"tags":["spark","iceberg","unsupported-operation","columnar"],"backgroundTag":"method-not-implemented","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}