{"record":{"id":"ac156fe427414aee","repo":"prestodb/presto","slug":"arrayoffset-is-negative-ac156f","errorCode":null,"errorMessage":"arrayOffset is negative","messagePattern":"arrayOffset is negative","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/block/IntArrayBlock.java","lineNumber":59,"sourceCode":"    public static final int SIZE_IN_BYTES_PER_POSITION = Integer.BYTES + Byte.BYTES;\n\n    private final int arrayOffset;\n    private final int positionCount;\n    @Nullable\n    private final boolean[] valueIsNull;\n    private final int[] values;\n\n    private final long retainedSizeInBytes;\n\n    public IntArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, int[] values)\n    {\n        this(0, positionCount, valueIsNull.orElse(null), values);\n    }\n\n    IntArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, int[] values)\n    {\n        if (arrayOffset < 0) {\n            throw new IllegalArgumentException(\"arrayOffset is negative\");\n        }\n        this.arrayOffset = arrayOffset;\n        if (positionCount < 0) {\n            throw new IllegalArgumentException(\"positionCount is negative\");\n        }\n        this.positionCount = positionCount;\n\n        if (values.length - arrayOffset < positionCount) {\n            throw new IllegalArgumentException(\"values length is less than positionCount\");\n        }\n        this.values = values;\n\n        if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {\n            throw new IllegalArgumentException(\"isNull length is less than positionCount\");\n        }\n        this.valueIsNull = valueIsNull;\n\n        retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/IntArrayBlock.java#L41-L77","documentation":"IntArrayBlock's package constructor validates arrayOffset, the starting index into the shared values/valueIsNull arrays. A negative arrayOffset would make all position indexing read before the start of the backing arrays, so the constructor throws IllegalArgumentException immediately.","triggerScenarios":"Constructing IntArrayBlock (directly or via the compact wrapper) with a negative arrayOffset, typically from slice.getArrayOffset()-style computations that produced -1 on failure or from manual offset arithmetic that underflowed.","commonSituations":"Block factory code reusing buffer segments where offset is computed as base - delta and delta exceeds base; wrapping subarrays after an empty-slice getArrayOffset() returning unexpected values.","solutions":["Ensure the arrayOffset passed is >= 0; check the computation that produces it.","Use the public two-arg constructor IntArrayBlock(positionCount, valueIsNull, values) which defaults arrayOffset to 0 when slicing is not needed.","Clamp negative offsets to 0 only if the underlying arrays actually start at index 0 (otherwise the data is misaligned — fix the producer)."],"exampleFix":"// before\nint offset = sliceStart - headerSize; // may be negative\nIntArrayBlock block = new IntArrayBlock(offset, count, nulls, values);\n// after\nint offset = Math.max(0, sliceStart - headerSize);\nIntArrayBlock block = new IntArrayBlock(offset, count, nulls, values);","handlingStrategy":"validation","validationCode":"if (arrayOffset < 0) {\n    throw new IllegalArgumentException(\"arrayOffset must be non-negative\");\n}\nIntArrayBlock block = new IntArrayBlock(arrayOffset, positionCount, valueIsNull, values);","typeGuard":"boolean validBlockArgs(int arrayOffset, int positionCount, int[] values) {\n    return arrayOffset >= 0 && positionCount >= 0 && values.length - arrayOffset >= positionCount;\n}","tryCatchPattern":"try {\n    block = new IntArrayBlock(offset, count, nulls, values);\n} catch (IllegalArgumentException e) {\n    block = new IntArrayBlock(count, Optional.empty(), values); // compact fallback\n}","preventionTips":["Prefer the public constructor that omits arrayOffset when not slicing","Check offset arithmetic (base - delta) for underflow","Assert offsets are non-negative in buffer-segment utilities"],"tags":["presto","block","illegal-argument","constructor"],"backgroundTag":"invalid-offset","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"}