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

  1. Re-acquire the serialized block and retry the transfer
  2. Align Presto versions across the cluster so encoding formats match
  3. 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

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


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