{"record":{"id":"c69e67222315514f","repo":"apache/cassandra","slug":"length-must-be-positive","errorCode":null,"errorMessage":"Length must be positive","messagePattern":"Length must be positive","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/io/util/MmappedRegions.java","lineNumber":115,"sourceCode":"    }\n\n    /**\n     * @param channel  file to map. the MmappedRegions instance will hold shared copy of given channel.\n     * @param metadata\n     * @return new instance\n     */\n    public static MmappedRegions map(ChannelProxy channel, CompressionMetadata metadata)\n    {\n        if (metadata == null)\n            throw new IllegalArgumentException(\"metadata cannot be null\");\n        State state = new State(channel);\n        return new MmappedRegions(state, metadata);\n    }\n\n    public static MmappedRegions map(ChannelProxy channel, long length, int chunkSize)\n    {\n        if (length <= 0)\n            throw new IllegalArgumentException(\"Length must be positive\");\n        State state = new State(channel);\n        return new MmappedRegions(state, length, chunkSize);\n    }\n\n    /**\n     * @return a snapshot of the memory mapped regions. The snapshot can\n     * only use existing regions, it cannot create new ones.\n     */\n    public MmappedRegions sharedCopy()\n    {\n        return new MmappedRegions(this);\n    }\n\n    private boolean isCopy()\n    {\n        return copy == null;\n    }\n","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/util/MmappedRegions.java#L97-L133","documentation":"MmappedRegions.map(ChannelProxy, long length, int chunkSize) validates that the file length used to size the mmap windows is strictly positive. A length <= 0 means there are no bytes to map, so mmap windows would be meaningless and the method refuses with IllegalArgumentException.","triggerScenarios":"Calling MmappedRegions.map(channel, length, chunkSize) with length = 0 or negative — e.g. mapping an empty or truncated file, a file whose length was read before it was fully written, or a computed length that underflowed (offset subtraction).","commonSituations":"Attempting to mmap a zero-byte sstable segment created by a failed/incomplete write; racing a reader against a writer that has not yet flushed any data; passing a stale or wrong file length captured before truncation.","solutions":["Check fileLength > 0 before calling map and skip mmap entirely for empty files","Re-read the file length at map time (channel.size()) rather than using a cached/stale value","Verify the file exists and was fully written (sync/flush completed) before mmapping","Fix length computations that can go negative (offset math, underflow)"],"exampleFix":"// before\nlong len = file.length();\nMmappedRegions regions = MmappedRegions.map(channel, len, chunkSize); // throws for empty file\n// after\nlong len = file.length();\nif (len > 0) {\n    regions = MmappedRegions.map(channel, len, chunkSize);\n} else {\n    regions = null; // nothing to map for an empty file\n}","handlingStrategy":"validation","validationCode":"long len = channel.size(); if (len <= 0) { skipMapping(); } else { MmappedRegions.map(channel, len, chunkSize); }","typeGuard":"boolean mappable = length > 0;","tryCatchPattern":"try { regions = MmappedRegions.map(channel, len, chunkSize); } catch (IllegalArgumentException e) { regions = null; }","preventionTips":["Check file size before mmapping","Handle empty files as a special case","Use channel.size() not a cached length"],"tags":["io","mmap","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}