{"record":{"id":"46979eeec2024cd0","repo":"prestodb/presto","slug":"isnull-length-is-less-than-positioncount-46979e","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/ByteArrayBlock.java","lineNumber":80,"sourceCode":"\n    ByteArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, byte[] 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 long getRegionSizeInBytes(int position, int length)\n    {\n        return SIZE_IN_BYTES_PER_POSITION * (long) length;\n    }\n","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/ByteArrayBlock.java#L62-L98","documentation":"ByteArrayBlock's constructor validates that, when a null-value map (valueIsNull) is supplied, it has at least positionCount entries after arrayOffset. If valueIsNull.length - arrayOffset < positionCount, the block could not answer isNull(position) for every valid position, so the library throws IllegalArgumentException. Passing null for valueIsNull is allowed and means no value is null.","triggerScenarios":"Calling new ByteArrayBlock(positionCount, valueIsNull, values, ...) with a valueIsNull array shorter than positionCount (minus arrayOffset); reusing a null map built for a smaller batch; supplying a valueIsNull array after slicing with an arrayOffset but forgetting to grow the array.","commonSituations":"Vectorized writers writing per-chunk null masks sized to the chunk not the block; serializers copying a null bitmap of the wrong bit-length; code paths that build valueIsNull only for nullable columns and pass an undersized stale array.","solutions":["Ensure valueIsNull.length - arrayOffset >= positionCount, or allocate valueIsNull = new boolean[positionCount]","Pass null for valueIsNull if no values are null (avoids the check and reduces retained size)","Resize the null mask before construction, e.g. Arrays.copyOf(isNull, positionCount)","Audit where the null mask is produced so its length always matches the values batch"],"exampleFix":"// before\nnew ByteArrayBlock(100, Optional.of(new boolean[64]), values, null); // throws\n// after\nnew ByteArrayBlock(100, Optional.of(new boolean[100]), values, null);","handlingStrategy":"validation","validationCode":"if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {\n    valueIsNull = Arrays.copyOfRange(valueIsNull, 0, positionCount); // pad to required length\n}\nBlock block = new ByteArrayBlock(positionCount, Optional.ofNullable(valueIsNull), values);\n","typeGuard":"boolean nullMaskCovers(boolean[] valueIsNull, int positionCount, int arrayOffset) {\n    return valueIsNull == null || valueIsNull.length - arrayOffset >= positionCount;\n}\n","tryCatchPattern":"try {\n    Block block = new ByteArrayBlock(positionCount, Optional.ofNullable(valueIsNull), values);\n} catch (IllegalArgumentException e) {\n    throw new IllegalStateException(\"null mask length must cover positionCount: \" + e.getMessage(), e);\n}\n","preventionTips":["Allocate null masks with exactly new boolean[positionCount]","Pass null (or Optional.empty()) when no value is null instead of reusing a small mask","Resize masks when batching multiple chunks into one block"],"tags":["presto","block-construction","illegal-argument","null-mask"],"backgroundTag":"block-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"}