prestodb/presto · critical · IllegalArgumentException
Deserialized SingleMapBlock violates invariants: key %d, val
Error message
Deserialized SingleMapBlock violates invariants: key %d, value %d
What it means
SingleMapBlockEncoding.readBlock deserializes key and value blocks plus an optional hash table from a SliceInput. It validates that keyBlock and valueBlock have equal position counts, because every map entry needs one key and one value. A mismatch means the serialized stream is corrupted or written by an incompatible producer, so readBlock throws IllegalArgumentException with the offending counts.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/SingleMapBlockEncoding.java:74
sliceOutput.appendInt(-1);
}
}
@Override
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 SingleMapBlock violates invariants: key %d, value %d", keyBlock.getPositionCount(), valueBlock.getPositionCount()));
}
if (hashTable != null && keyBlock.getPositionCount() * HASH_MULTIPLIER != hashTable.length) {
throw new IllegalArgumentException(
format("Deserialized SingleMapBlock violates invariants: expected hashtable size %d, actual hashtable size %d", keyBlock.getPositionCount() * HASH_MULTIPLIER, hashTable.length));
}
MapBlock mapBlock = MapBlock.createMapBlockInternal(
0,
1,
Optional.empty(),
new int[] {0, keyBlock.getPositionCount()},
keyBlock,
valueBlock,
new HashTables(Optional.ofNullable(hashTable), 1));
return new SingleMapBlock(0, 0, keyBlock.getPositionCount() * 2, mapBlock);View on GitHub (pinned to 55bb57d202)
Solutions
- Verify all nodes run the same Presto version; roll back or upgrade to align serialization formats.
- Re-generate the corrupted spill/exchange data or retry the query; if corruption recurs, check storage/network integrity.
- If a custom serializer produced the bytes, fix the writer so it emits key and value blocks with identical position counts.
- Add a checksum/validation layer on serialized pages to detect truncation early.
Example fix
// before // writer emits keys and values from different sources SliceOutput out = ...; blockEncodings.writeBlock(out, keyBlock); blockEncodings.writeBlock(out, valueBlock.slice(0, keyBlock.getPositionCount() - 1)); // mismatch // after checkState(keyBlock.getPositionCount() == valueBlock.getPositionCount()); blockEncodings.writeBlock(out, keyBlock); blockEncodings.writeBlock(out, valueBlock);
Defensive patterns
Strategy: try-catch
Validate before calling
// before decoding, sanity-check the serialized stream size
if (sliceInput.available() < MIN_MAP_BLOCK_BYTES) {
throw new IOException("truncated map block payload");
} Try / catch
try {
Block block = blockEncoding.readBlock(sliceInput);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Deserialized SingleMapBlock violates invariants")) {
throw new CorruptedPageException("Discard/regenerate spill or exchange data; check cluster version skew", e);
}
throw e;
} Prevention
- Keep all cluster nodes on the same Presto version.
- Enable checksums on spill/exchange storage to catch truncation.
- Never hand-write block encodings; use the provided BlockEncodingSerde.
When it happens
Trigger: Reading a MapBlock from serialized page data where the key block's positionCount differs from the value block's positionCount (e.g. truncated stream, wrong byte offsets, cross-version serialization incompatibility, or data written by a buggy custom serializer).
Common situations: Exchange/spill file corruption, mixing Presto versions in a cluster (different block encodings), third-party connectors writing raw serialized blocks, network truncation.
Related errors
- Deserialized SingleMapBlock violates invariants: expected ha
- INVALID_FUNCTION_ARGUMENT
- NOT_SUPPORTED
- Offset is not monotonically ascending. offsets[%s]=%s, offse
- A null map must have zero entries
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/2a17c708b2c4fa18.
Report an issue: GitHub.