apache/flink · error · UnsupportedOperationException
Only support seek at first.
Error message
Only support seek at first.
What it means
UnsupportedOperationException from seekToRow(long) in ParquetColumnarRowSplitReader: seeking is only allowed before any row group has been loaded. The guard is totalCountLoadedSoFar != 0, which becomes non-zero as soon as a row group is read or a previous seek skipped row groups. The design is one-shot: position once, then stream forward.
Source
Thrown at flink-formats/flink-parquet/src/main/java/org/apache/flink/formats/parquet/vector/ParquetColumnarRowSplitReader.java:345
columnReaders = new ColumnReader[types.size()];
for (int i = 0; i < types.size(); ++i) {
columnReaders[i] =
createColumnReader(
utcTimestamp,
selectedTypes[i],
types.get(i),
requestedSchema.getColumns(),
pages,
fieldList.get(i),
0);
}
totalCountLoadedSoFar += pages.getRowCount();
}
/** Seek to a particular row number. */
public void seekToRow(long rowCount) throws IOException {
if (totalCountLoadedSoFar != 0) {
throw new UnsupportedOperationException("Only support seek at first.");
}
List<BlockMetaData> blockMetaData = reader.getRowGroups();
for (BlockMetaData metaData : blockMetaData) {
if (metaData.getRowCount() > rowCount) {
break;
} else {
reader.skipNextRowGroup();
rowsReturned += metaData.getRowCount();
totalCountLoadedSoFar += metaData.getRowCount();
rowsInBatch = (int) metaData.getRowCount();
nextRow = (int) metaData.getRowCount();
rowCount -= metaData.getRowCount();
}
}
for (int i = 0; i < rowCount; i++) {
boolean end = reachedEnd();View on GitHub (pinned to 2f3c205e92)
Solutions
- Create a fresh ParquetColumnarRowSplitReader per seek: close the old one, reopen on the same InputFile, then seekToRow
- Restructure the consumer to do a single seek up front and only read forward afterwards
- For repeated random access, cache the rows you need instead of re-seeking the streaming reader
Example fix
// before reader.seekToRow(100); ... read ... reader.seekToRow(500); // UnsupportedOperationException // after reader.close(); reader = newReader(inputFile, ...); reader.seekToRow(500);
Defensive patterns
Strategy: validation
Validate before calling
if (reader.hasLoadedData()) { throw new IllegalStateException("seekToRow only valid before reading - recreate the reader"); } // or track your own 'readStarted' flag Prevention
- Treat ParquetColumnarRowSplitReader as forward-only: one seek, then stream
- Create a new reader instance per reposition instead of re-seeking
When it happens
Trigger: Calling seekToRow(rowCount) a second time, or calling it after nextRecord()/reachedEnd() has already caused a row group to load, on the same reader instance.
Common situations: Reusing a reader for random access (e.g. implementing sampling or offset-based retries); upper layers assuming a seekable cursor API like a JDBC result set; iterator wrappers that rewind and re-seek on the same split.
Related errors
- Only support seek at first.
- Please use AvroParquetReaders.forSpecificRecord(Class<T>) fo
- Seek to many rows.
- Accessing a field by position is not supported in name-based
- Accessing a field by name is not supported in position-based
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/18d3ecf6045c55b7.
Report an issue: GitHub.