{"record":{"id":"759ff3823c3974d2","repo":"prestodb/presto","slug":"length-d-must-be-a-multiple-of-16","errorCode":null,"errorMessage":"length %d must be a multiple of 16.","messagePattern":"length (.+?) must be a multiple of 16\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/block/BlockUtil.java","lineNumber":285,"sourceCode":"        newIsNull[desiredLength - 1] = true;\n        return newIsNull;\n    }\n\n    static int[] appendNullToOffsetsArray(int[] offsets, int offsetBase, int positionCount)\n    {\n        checkArrayRange(offsets, offsetBase, positionCount + 1);\n\n        int desiredLength = offsetBase + positionCount + 2;\n        int[] newOffsets = Arrays.copyOf(offsets, desiredLength);\n        newOffsets[desiredLength - 1] = newOffsets[desiredLength - 2];\n        return newOffsets;\n    }\n\n    public static int getNum128Integers(int length)\n    {\n        int num128Integers = length / SIZE_OF_LONG / 2;\n        if (num128Integers * SIZE_OF_LONG * 2 != length) {\n            throw new IllegalArgumentException(format(\"length %d must be a multiple of 16.\", length));\n        }\n        return num128Integers;\n    }\n\n    /**\n     * Returns the input blocks array if all blocks are already loaded, otherwise returns a new blocks array with all blocks loaded\n     */\n    static Block[] ensureBlocksAreLoaded(Block[] blocks)\n    {\n        for (int i = 0; i < blocks.length; i++) {\n            Block loaded = blocks[i].getLoadedBlock();\n            if (loaded != blocks[i]) {\n                // Transition to new block creation mode after the first newly loaded block is encountered\n                Block[] loadedBlocks = blocks.clone();\n                loadedBlocks[i++] = loaded;\n                for (; i < blocks.length; i++) {\n                    loadedBlocks[i] = blocks[i].getLoadedBlock();\n                }","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/BlockUtil.java#L267-L303","documentation":"BlockUtil.getNum128Integers converts a byte length into a count of 128-bit integers (length / 16). Because the conversion only works for whole 128-bit units, the length must be an exact multiple of 16 (SIZE_OF_LONG * 2); otherwise the operation would silently truncate partial data, so the library throws this IllegalArgumentException. It is a strict alignment requirement on the input length.","triggerScenarios":"Calling getNum128Integers with a length that is not divisible by 16, e.g. getNum128Integers(20) or getNum128Integers(0-modulo-8-only sizes like 8 or 24). Usually reached from fixed-width block/vectorized hashing paths where a buffer was sliced to a non-aligned boundary.","commonSituations":"Custom slice/buffer arithmetic producing misaligned lengths (off-by-N slicing of a fixed-width value buffer); a custom block type whose element size is not 16 bytes being fed into a 128-bit vectorized routine; version changes where value widths changed but the hash path assumed 16-byte alignment.","solutions":["Ensure the input length is a multiple of 16 before calling: round/slice the buffer to whole 128-bit units.","Verify the byte width of the values being processed is 16 (two longs); if the data is narrower, use the correct vectorized helper for that width.","Check slicing logic upstream (offsets/lengths math) for misalignment; add an assertion length % 16 == 0 where buffers are constructed."],"exampleFix":"// before\nint n = BlockUtil.getNum128Integers(sliceLength); // throws when sliceLength % 16 != 0\n// after\ncheckArgument(sliceLength % 16 == 0, \"length must be a multiple of 16, got %s\", sliceLength);\nint n = BlockUtil.getNum128Integers(sliceLength);","handlingStrategy":"validation","validationCode":"if (length < 0 || length % 16 != 0) {\n    throw new IllegalArgumentException(\"length must be a non-negative multiple of 16: \" + length);\n}\nint num128Integers = BlockUtil.getNum128Integers(length);","typeGuard":"boolean is16ByteAligned(int length) {\n    return length >= 0 && (length & 15) == 0;\n}","tryCatchPattern":"try {\n    n = BlockUtil.getNum128Integers(length);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"must be a multiple of 16\")) {\n        throw new IllegalStateException(\"misaligned buffer passed to 128-bit path: \" + length, e);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Assert length % 16 == 0 wherever fixed-width 16-byte buffers are sliced.","Verify element byte widths before routing data into 128-bit vectorized helpers.","Recheck slicing/offset math after changing fixed-width type sizes.","Add round-trip tests that slice buffers at every supported width."],"tags":["presto","block","alignment","vectorization"],"backgroundTag":"unaligned-buffer-length","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}