apache/iceberg · error · UnsupportedOperationException

Batch reading is not supported in Avro reader

Error message

Batch reading is not supported in Avro reader

What it means

The Avro format model's ReadBuilder.recordsPerBatch is unsupported because the Avro reader returns an iterator of individual records rather than columnar batches. Calling it always throws UnsupportedOperationException. Batch-oriented reads (e.g. Arrow/Vectorized readers) are only available for columnar formats like Parquet.

Source

Thrown at core/src/main/java/org/apache/iceberg/avro/AvroFormatModel.java:252

      // This is not an error since filtering is best-effort.
      return this;
    }

    @Override
    public ReadBuilder<D, S> set(String key, String value) {
      // Configuration is not used for Avro reader creation
      return this;
    }

    @Override
    public ReadBuilder<D, S> reuseContainers() {
      internal.reuseContainers();
      return this;
    }

    @Override
    public ReadBuilder<D, S> recordsPerBatch(int numRowsPerBatch) {
      throw new UnsupportedOperationException("Batch reading is not supported in Avro reader");
    }

    @Override
    public ReadBuilder<D, S> idToConstant(Map<Integer, ?> newIdToConstant) {
      this.idToConstant = newIdToConstant;
      return this;
    }

    @Override
    public ReadBuilder<D, S> withNameMapping(org.apache.iceberg.mapping.NameMapping nameMapping) {
      internal.withNameMapping(nameMapping);
      return this;
    }

    @Override
    public CloseableIterable<D> build() {
      // The file schema is passed directly to the DatumReader by the Avro read path, so null is
      // passed here

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Use the record-at-a-time read path for Avro (omit recordsPerBatch and iterate the returned iterator)
  2. Configure the read path to disable batching/vectorization for Avro files
  3. Use Parquet when batched reads are required
  4. Branch on format model capability before calling recordsPerBatch

Example fix

// before
CloseableIterator<ColumnBatch<T>> it =
    readBuilder(io, file).recordsPerBatch(1024).build(); // avro: throws

// after
CloseableIterator<T> it = readBuilder(io, file).build(); // record iterator
Defensive patterns

Strategy: validation

Validate before calling

if ("avro".equals(fileFormat) && batchSize > 0) { throw new IllegalArgumentException("Batching unsupported for Avro reads"); }

Type guard

boolean supportsBatchRead(FormatModel m) { return !(m instanceof AvroFormatModel); }

Try / catch

try { builder.recordsPerBatch(n).build(); } catch (UnsupportedOperationException e) { /* fall back to record-at-a-time iterator */ }

Prevention

When it happens

Trigger: Calling readBuilder(...).recordsPerBatch(n).build() on an Avro file/table scan, typically in vectorized-read code paths that assume a batch-capable format model.

Common situations: Generic batch-read code shared across Parquet/Avro/ORC writers applied to Avro; engine integrations requesting batches for all formats; configuration that enables vectorized/batch reading without checking the file format.

Related errors


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