{"record":{"id":"e96fa59a46eb8b12","repo":"quarkusio/quarkus","slug":"offset-offset-must-be-0-file","errorCode":null,"errorMessage":"Offset (${offset}) must be >= 0: ${file}","messagePattern":"Offset \\((.+?)\\) must be >= 0: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/FilePart.java","lineNumber":40,"sourceCode":"     */\n    public final long count;\n\n    /**\n     * Create a new partial {@link File} object.\n     *\n     * @param file The file to send\n     * @param offset The starting byte of the file (must be >= 0)\n     * @param count The number of bytes to send (must be >= 0 and offset+count <= file size)\n     */\n    public FilePart(File file, long offset, long count) {\n        if (!file.exists())\n            throw new IllegalArgumentException(\"File does not exist: \" + file);\n        if (!file.isFile())\n            throw new IllegalArgumentException(\"File is not a regular file: \" + file);\n        if (!file.canRead())\n            throw new IllegalArgumentException(\"File cannot be read: \" + file);\n        if (offset < 0)\n            throw new IllegalArgumentException(\"Offset (\" + offset + \") must be >= 0: \" + file);\n        if (count < 0)\n            throw new IllegalArgumentException(\"Count (\" + count + \") must be >= 0: \" + file);\n        if ((offset + count) > file.length())\n            throw new IllegalArgumentException(\n                    \"Offset + count (\" + (offset + count) + \") larger than file size (\" + file.length() + \"): \" + file);\n        this.file = file;\n        this.offset = offset;\n        this.count = count;\n    }\n}\n","sourceCodeStart":22,"sourceCodeEnd":51,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/FilePart.java#L22-L51","documentation":"FilePart sends a byte range of a file, so the starting offset must be non-negative. A negative offset would read outside the file's bounds, and the constructor rejects it with this IllegalArgumentException naming both the offset and the file.","triggerScenarios":"new FilePart(file, offset, count) with a negative offset, commonly from an unsigned-offset arithmetic bug or a computed resume position going below zero.","commonSituations":"Computing offset from a 'resume' marker where bytes-sent was larger than file size; parsing a user-provided range header value without clamping; int/long subtraction underflow when chunking uploads.","solutions":["Clamp the offset to 0 before constructing the FilePart (Math.max(0, offset)).","Fix the upstream arithmetic that produced the negative offset (check the resume/chunk computation).","Validate any user-provided offset input before passing it in."],"exampleFix":"// before\nlong offset = sentBytes - totalSize;\nnew FilePart(file, offset, count);\n// after\nlong offset = Math.max(0, sentBytes);\nnew FilePart(file, offset, count);","handlingStrategy":"validation","validationCode":"if (offset < 0) throw new IllegalStateException(\"Invalid offset \" + offset + \" for \" + file);\nFilePart part = new FilePart(file, offset, count);","typeGuard":"static boolean isValidRange(File f, long offset, long count) {\n    return f != null && offset >= 0 && count >= 0 && offset + count <= f.length();\n}","tryCatchPattern":"try {\n    return new FilePart(file, offset, count);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Offset (\")) {\n        log.warn(\"Bad offset {} for {}, clamping to 0\", offset, file);\n        return new FilePart(file, 0, count);\n    }\n    throw e;\n}","preventionTips":["Clamp offsets with Math.max(0, offset)","Validate range-header values parsed from user input","Watch for arithmetic that can underflow when computing resume positions"],"tags":["io","argument-validation","multipart"],"backgroundTag":"invalid-range-offset","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}