prestodb/presto · error · ParquetDecodingException

not a valid mode

Error message

not a valid mode 

What it means

BinaryRLEDictionaryValuesDecoder.readNext fills value buffers from RLE/bit-packed dictionary indices; the mode switch only supports RLE and PACKED_BIT_PACKED. An unknown mode in the index stream's run header makes the dictionary-id data undecodable, so a ParquetDecodingException is thrown with this.mode. It indicates corrupt or unsupported dictionary index data.

Source

Thrown at presto-parquet/src/main/java/com/facebook/presto/parquet/batchreader/decoders/rle/BinaryRLEDictionaryValuesDecoder.java:80

                    final int rleValueLength = dictionary.getLength(rleValue);
                    while (destinationIndex < endIndex) {
                        dictionaries[destinationIndex++] = rleValue;
                    }
                    bufferSize += (rleValueLength * numEntriesToFill);
                    break;
                }
                case PACKED: {
                    final int[] localBuffer = currentBuffer;
                    final BinaryBatchDictionary localDictionary = dictionary;
                    for (int srcIndex = currentBuffer.length - currentCount; destinationIndex < endIndex; srcIndex++, destinationIndex++) {
                        int dictionaryId = localBuffer[srcIndex];
                        dictionaries[destinationIndex] = dictionaryId;
                        bufferSize += localDictionary.getLength(dictionaryId);
                    }
                    break;
                }
                default:
                    throw new ParquetDecodingException("not a valid mode " + this.mode);
            }
            currentCount -= numEntriesToFill;
            remainingToCopy -= numEntriesToFill;
        }

        checkState(remainingToCopy == 0, "Invalid read size request");
        return new RLEValueBuffer(bufferSize, dictionaries);
    }

    @Override
    public int readIntoBuffer(byte[] byteBuffer, int bufferIndex, int[] offsets, int offsetIndex, ValueBuffer valueBuffer)
    {
        checkArgument(byteBuffer.length - bufferIndex >= valueBuffer.getBufferSize(), "not enough space in the input buffer");

        RLEValueBuffer rleValueBuffer = (RLEValueBuffer) valueBuffer;
        final int[] dictionaryIds = rleValueBuffer.getDictionaryIds();
        final int numEntries = dictionaryIds.length;

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Validate the column chunk with parquet-tools (it will also fail if data is corrupt)
  2. Disable dictionary reading issues by rewriting the file without dictionary encoding or with a standard writer
  3. Restore the file from a clean source and compare checksums
  4. Upgrade presto-parquet if a newer writer encoding is involved; otherwise file a bug with file metadata

Example fix

// before: file with corrupt dictionary index header
// after: rewrite without dictionary encoding to sidestep the bad header
//   parquet.writer.dictionary=false (writer config) or rewrite via Spark/Trino
Defensive patterns

Strategy: try-catch

Validate before calling

// parquet-tools meta file.parquet | grep <column>  # confirm RLE_DICTIONARY/PLAIN_DICTIONARY and intact chunk sizes

Try / catch

try {
    decoder.readNext(batchSize);
} catch (ParquetDecodingException e) {
    if (e.getMessage().startsWith("not a valid mode")) {
        // retry against a re-written copy of the file; do not loop-retry the same bytes
    }
    throw e;
}

Prevention

When it happens

Trigger: readNext() reaches the default branch because a run header in the dictionary-index stream encodes a mode outside Mode.RLE/Mode.PACKED_BIT_PACKED.

Common situations: Corrupted dictionary-encoded column chunks; files produced by writers emitting non-standard hybrid headers; byte-offset misalignment after earlier decode errors causing headers to be read at wrong positions.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/1e7b5f5cfb601589. Report an issue: GitHub.