quarkusio/quarkus · error · IllegalArgumentException

Offset (${offset}) must be >= 0: ${file}

Error message

Offset (${offset}) must be >= 0: ${file}

What it means

PathPart models a byte range [offset, offset+count) of a file. The constructor rejects a negative offset with this IllegalArgumentException, since a negative start position has no meaning for a file range.

Source

Thrown at independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/PathPart.java:43

     */
    public final long count;

    /**
     * Create a new partial {@link Path} object.
     *
     * @param file The file to send
     * @param offset The starting byte of the file (must be >= 0)
     * @param count The number of bytes to send (must be >= 0 and offset+count <= file size)
     */
    public PathPart(Path file, long offset, long count) {
        if (!Files.exists(file))
            throw new IllegalArgumentException("File does not exist: " + file);
        if (!Files.isRegularFile(file))
            throw new IllegalArgumentException("File is not a regular file: " + file);
        if (!Files.isReadable(file))
            throw new IllegalArgumentException("File cannot be read: " + file);
        if (offset < 0)
            throw new IllegalArgumentException("Offset (" + offset + ") must be >= 0: " + file);
        if (count < 0)
            throw new IllegalArgumentException("Count (" + count + ") must be >= 0: " + file);
        long fileLength;
        try {
            fileLength = Files.size(file);
            if ((offset + count) > fileLength)
                throw new IllegalArgumentException(
                        "Offset + count (" + (offset + count) + ") larger than file size (" + fileLength + "): " + file);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
        this.file = file;
        this.offset = offset;
        this.count = count;
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Clamp or reject negative offsets before construction: `if (offset < 0) offset = 0;` or return 416 Range Not Satisfiable.
  2. When parsing Range headers, treat suffix ranges (`bytes=-N`) explicitly instead of passing -1 as the start.
  3. Validate numeric inputs from client requests before using them as offsets.

Example fix

// before
long start = parseRangeStart(header); // may be -1
PathPart part = new PathPart(file, start, count);
// after
long start = parseRangeStart(header);
if (start < 0) {
    return Response.status(Response.Status.REQUESTED_RANGE_NOT_SATISFIABLE).build();
}
PathPart part = new PathPart(file, start, count);
Defensive patterns

Strategy: validation

Validate before calling

if (offset < 0) {
    return Response.status(Response.Status.REQUESTED_RANGE_NOT_SATISFIABLE).build();
}

Type guard

boolean isValidStart(long offset) {
    return offset >= 0;
}

Try / catch

try {
    return Response.ok(new PathPart(file, offset, count)).build();
} catch (IllegalArgumentException e) {
    return Response.status(Response.Status.REQUESTED_RANGE_NOT_SATISFIABLE).build();
}

Prevention

When it happens

Trigger: Calling `new PathPart(file, offset, count)` with `offset < 0`, typically when offset comes from parsing a client's Range header (e.g. `bytes=-500`) or from an unchecked numeric field.

Common situations: Parsing partial Range headers where the start value is absent and a sentinel -1 is passed through; integer underflow computing offsets; client-supplied offsets not validated in custom range-handling code.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/8e05beb768356b75. Report an issue: GitHub.