apache/iceberg · error · UnsupportedOperationException
Unsupported mode for timestamp int96 reader: " + mode
Error message
Unsupported mode for timestamp int96 reader: " + mode
What it means
TimestampInt96Reader.nextDictEncodedVal dispatches on the decode Mode (the dictionary decoding strategy) and throws UnsupportedOperationException for any Mode it does not explicitly implement. Only the modes handled in its switch produce values; others are treated as unsupported for INT96 timestamp dictionary reads.
Source
Thrown at arrow/src/main/java/org/apache/iceberg/arrow/vectorized/parquet/VectorizedParquetDefinitionLevelReader.java:545
int numValues,
NullabilityHolder holder,
int typeWidth) {
switch (mode) {
case RLE:
reader
.timestampInt96DictEncodedReader()
.nextBatch(vector, idx, numValues, dict, holder, typeWidth);
break;
case PACKED:
ByteBuffer buffer =
dict.decodeToBinary(reader.readInteger())
.toByteBuffer()
.order(ByteOrder.LITTLE_ENDIAN);
long timestampInt96 = ParquetUtil.extractTimestampInt96(buffer);
vector.getDataBuffer().setLong((long) idx * typeWidth, timestampInt96);
break;
default:
throw new UnsupportedOperationException(
"Unsupported mode for timestamp int96 reader: " + mode);
}
}
}
class FixedSizeBinaryReader extends BaseReader {
@Override
protected void nextVal(
FieldVector vector,
int idx,
VectorizedValuesReader valuesReader,
int typeWidth,
byte[] byteArray) {
valuesReader.readBinary(typeWidth).toByteBuffer().get(byteArray, 0, typeWidth);
((FixedSizeBinaryVector) vector).set(idx, byteArray);
}
@OverrideView on GitHub (pinned to 86d9c8fc54)
Solutions
- Rewrite the data with INT64 (TIMESTAMP_MICROS/MILLIS) logical type instead of INT96.
- Disable vectorized reads for these files to use the non-vectorized path.
- Add the missing Mode case to TimestampInt96Reader.nextDictEncodedVal if it should be supported.
Example fix
// before
throw new UnsupportedOperationException("Unsupported mode for timestamp int96 reader: " + mode);
// after
case RLE_DICTIONARY: // add the missing mode
decodeWithRleDictionary(vector, idx, reader, dict, numValues, holder, typeWidth);
break;
default:
throw new UnsupportedOperationException("Unsupported mode for timestamp int96 reader: " + mode); Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check encoding before vectorized INT96 dictionary decode
boolean isInt96 = desc.getPrimitiveType().getPrimitiveTypeName() == PrimitiveTypeName.INT96;
boolean dictEncoded = pageEncoding != null && pageEncoding.isDictionaryEncoded();
if (isInt96 && dictEncoded) { disableVectorization = true; } Try / catch
try {
reader.nextDictEncodedVal(vector, idx, dictReader, dict, mode, numValues, holder, typeWidth);
} catch (UnsupportedOperationException e) {
throw new IllegalArgumentException("INT96 dict decode mode unsupported: " + mode, e);
} Prevention
- Convert INT96 timestamps to INT64 logical timestamps during ingestion/compaction.
- Disable vectorized reads for legacy INT96 datasets.
- Keep custom decode modes in sync with TimestampInt96Reader switch cases.
- Test with representative legacy files before enabling vectorization fleet-wide.
When it happens
Trigger: Reading dictionary-encoded INT96 (legacy timestamp) Parquet pages where the dictionary decode Mode passed to nextDictEncodedVal is not one of the implemented variants, during packed dictionary decoding of rows (e.g. from timestampInt96ReaderPackedDictionaryDecodeDecodesRowsCorrectly).
Common situations: Reading legacy Hive/Spark 1.x/Impala-written Parquet files that store timestamps as INT96 with dictionary encoding, consumed via the Iceberg vectorized Arrow reader using an unimplemented decode mode.
Related errors
- UnsupportedOperationException with no message (TimestampInt9
- Unsupported base type for decimal:
- Unsupported logical type: " + primitive.getOriginalType()
- Unsupported type: " + primitive
- could not read page in col " + desc + " as the dictionary wa
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/206278080dd7d490.
Report an issue: GitHub.