{"record":{"id":"bbc04719013a91ff","repo":"prestodb/presto","slug":"isnull-length-is-less-than-positioncount-bbc047","errorCode":null,"errorMessage":"isNull length is less than positionCount","messagePattern":"isNull length is less than positionCount","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/block/ShortArrayBlock.java","lineNumber":71,"sourceCode":"\n    ShortArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, short[] 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);\n    }\n\n    @Override\n    public long getSizeInBytes()\n    {\n        return SIZE_IN_BYTES_PER_POSITION * (long) positionCount;\n    }\n\n    @Override\n    public OptionalInt fixedSizeInBytesPerPosition()\n    {\n        return OptionalInt.of(SIZE_IN_BYTES_PER_POSITION);\n    }\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/ShortArrayBlock.java#L53-L89","documentation":"ShortArrayBlock validates that the optional valueIsNull boolean array is at least arrayOffset + positionCount long whenever it is non-null. If isNull is shorter than the block's position range, null-lookups would read out of bounds, so the constructor throws IllegalArgumentException. The values and isNull arrays must have consistent capacity.","triggerScenarios":"Constructing ShortArrayBlock with a non-null valueIsNull array where valueIsNull.length - arrayOffset < positionCount.","commonSituations":"Allocating the null mask from a different length source than the values array (e.g. reusing a stale mask after resizing), copy/paste where only values were grown, corrupted input data.","solutions":["Allocate valueIsNull with length >= arrayOffset + positionCount, mirroring values sizing.","Pass null if no nulls are possible instead of an undersized mask.","Assert Arrays consistency: requireNonNull sizing helper before construction."],"exampleFix":"// before\nboolean[] isNull = new boolean[positionCount / 2];\nnew ShortArrayBlock(arrayOffset, positionCount, values, isNull);\n// after\nboolean[] isNull = new boolean[arrayOffset + positionCount];\nnew ShortArrayBlock(arrayOffset, positionCount, values, isNull);","handlingStrategy":"validation","validationCode":"if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {\n    throw new IllegalArgumentException(\"valueIsNull too small: need \" + (arrayOffset + positionCount) + \", have \" + valueIsNull.length);\n}","typeGuard":"boolean nullMaskFits(int arrayOffset, int positionCount, boolean[] valueIsNull) {\n    return valueIsNull == null || valueIsNull.length - arrayOffset >= positionCount;\n}","tryCatchPattern":"try {\n    block = new ShortArrayBlock(arrayOffset, positionCount, values, valueIsNull);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"isNull length is less than positionCount\")) {\n        valueIsNull = valueIsNull == null ? null : Arrays.copyOf(valueIsNull, arrayOffset + positionCount);\n        block = new ShortArrayBlock(arrayOffset, positionCount, values, valueIsNull);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Keep values and valueIsNull sizing logic in a single helper so they can never diverge.","Pass null instead of an undersized mask when the block has no nulls.","After resizing values, always resize the null mask to match."],"tags":["presto","block","illegal-argument","null-mask"],"backgroundTag":"array-length-mismatch","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"}