prestodb/presto · error · IllegalArgumentException
Deserialized MapBlock violates invariants: expected hashtabl
Error message
Deserialized MapBlock violates invariants: expected hashtable size %d, actual hashtable size %d
What it means
readBlock additionally checks that the optional hash table, when present, has exactly positionCount * HASH_MULTIPLIER entries, as Presto's map hash tables are sized by a fixed multiplier of the entry count. Any other length indicates a corrupt or hand-crafted serialized block and throws IllegalArgumentException.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/MapBlockEncoding.java:92
public Block readBlock(BlockEncodingSerde blockEncodingSerde, SliceInput sliceInput)
{
Block keyBlock = blockEncodingSerde.readBlock(sliceInput);
Block valueBlock = blockEncodingSerde.readBlock(sliceInput);
int hashTableLength = sliceInput.readInt();
int[] hashTable = null;
if (hashTableLength >= 0) {
hashTable = new int[hashTableLength];
sliceInput.readBytes(wrappedIntArray(hashTable));
}
if (keyBlock.getPositionCount() != valueBlock.getPositionCount()) {
throw new IllegalArgumentException(
format("Deserialized MapBlock violates invariants: key %d, value %d", keyBlock.getPositionCount(), valueBlock.getPositionCount()));
}
if (hashTable != null && keyBlock.getPositionCount() * HASH_MULTIPLIER != hashTable.length) {
throw new IllegalArgumentException(
format("Deserialized MapBlock violates invariants: expected hashtable size %d, actual hashtable size %d", keyBlock.getPositionCount() * HASH_MULTIPLIER, hashTable.length));
}
int positionCount = sliceInput.readInt();
int[] offsets = new int[positionCount + 1];
sliceInput.readBytes(wrappedIntArray(offsets));
Optional<boolean[]> mapIsNull = EncoderUtil.decodeNullBits(sliceInput, positionCount);
return MapType.createMapBlockInternal(0, positionCount, mapIsNull, offsets, keyBlock, valueBlock, new HashTables(Optional.ofNullable(hashTable), positionCount));
}
}
View on GitHub (pinned to 55bb57d202)
Solutions
- Re-acquire the serialized block and retry the transfer
- Align Presto versions across the cluster so encoding formats match
- Add checksum validation on the transfer channel that carries block bytes
Defensive patterns
Strategy: try-catch
Try / catch
try {
Block block = blockEncoding.readBlock(sliceInput);
} catch (IllegalArgumentException e) {
// treat as corrupt payload: retry transfer or recompute
} Prevention
- Validate slice offsets/lengths before deserialization
- Verify HASH_MULTIPLIER-based table sizing in custom writers
- Add integration tests covering serialized round-trips
When it happens
Trigger: Deserializing a MapBlock whose hashTableLength field is nonzero and != keyBlock.getPositionCount() * HASH_MULTIPLIER — corrupted slice, misaligned read offsets, or writer/deserializer version mismatch.
Common situations: Bytes shifted by an earlier misread field; incompatible wire format across Presto versions; manual manipulation of serialized block data in tests.
Related errors
- Deserialized MapBlock violates invariants: key %d, value %d
- DuplicateMapKeyException
- NOT_SUPPORTED
- BIGQUERY_ERROR_READING_NEXT_AVRO_RECORD
- Offset is not monotonically ascending. offsets[%s]=%s, offse
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/fdb2851bd61f18dd.
Report an issue: GitHub.