{"record":{"id":"c060898b7dc71511","repo":"apache/flink","slug":"offset-cannot-be-negative","errorCode":null,"errorMessage":"Offset cannot be negative.","messagePattern":"Offset cannot be negative\\.","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/core/memory/DataInputDeserializer.java","lineNumber":385,"sourceCode":"            this.position = this.end;\n            return n;\n        }\n    }\n\n    @Override\n    public void skipBytesToRead(int numBytes) throws IOException {\n        int skippedBytes = skipBytes(numBytes);\n\n        if (skippedBytes < numBytes) {\n            throw new EOFException(\"Could not skip \" + numBytes + \" bytes.\");\n        }\n    }\n\n    @Override\n    public int read(@Nonnull byte[] b, int off, int len) throws IOException {\n\n        if (off < 0) {\n            throw new IndexOutOfBoundsException(\"Offset cannot be negative.\");\n        }\n\n        if (len < 0) {\n            throw new IndexOutOfBoundsException(\"Length cannot be negative.\");\n        }\n\n        if (b.length - off < len) {\n            throw new IndexOutOfBoundsException(\n                    \"Byte array does not provide enough space to store requested data\" + \".\");\n        }\n\n        if (this.position >= this.end) {\n            return len == 0 ? 0 : -1;\n        } else {\n            int toRead = Math.min(this.end - this.position, len);\n            System.arraycopy(this.buffer, this.position, b, off, toRead);\n            this.position += toRead;\n","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/core/memory/DataInputDeserializer.java#L367-L403","documentation":"Thrown by DataInputDeserializer.read(byte[], int off, int len) when off is negative. This read overload validates the destination offset before any copy, giving a clear message instead of an opaque array exception.","triggerScenarios":"Calling read(b, off, len) (or read(b) which delegates with off=0, so won't trigger) with off < 0.","commonSituations":"Caller computes an offset that underflows to negative; a default/uninitialized offset variable; off-by-one in a buffer-filling loop.","solutions":["Ensure off >= 0 before calling read(b, off, len).","Use read(byte[]) when writing into the whole destination array.","Validate off+len <= b.length as a combined precondition."],"exampleFix":"// before\ninput.read(dst, writePos, n); // writePos may be < 0\n\n// after\nif (writePos < 0 || writePos + n > dst.length) {\n    throw new IndexOutOfBoundsException(\"bad dst range\");\n}\ninput.read(dst, writePos, n);","handlingStrategy":"validation","validationCode":"if (off < 0) {\n    throw new IndexOutOfBoundsException(\"off must be >= 0, got \" + off);\n}\ninput.read(dst, off, len);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer read(byte[]) when writing into the whole destination array.","Validate off and len together: off >= 0 && len >= 0 && off + len <= dst.length.","Initialize offset accumulators to 0, never to a sentinel like -1."],"tags":["serialization","bounds-check","deserialization","validation"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}