quarkusio/quarkus · error · IllegalArgumentException
File is not a regular file: ${file}
Error message
File is not a regular file: ${file} What it means
PathPart wraps a regular file for range-based response streaming. It throws this IllegalArgumentException when the Path exists but is not a regular file (e.g. a directory or special file), because only regular files support byte-range reads of a known size.
Source
Thrown at independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/PathPart.java:39
public final long offset;
/**
* The number of bytes to send
*/
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
- Check `Files.isDirectory(file)` in the caller and return 404 or redirect instead of constructing PathPart.
- Point PathPart at the concrete file, not a directory; append the filename when the user requests a folder path.
- Normalize/validate user-supplied paths (reject directory or symlink targets) before constructing the part.
Example fix
// before
Path requested = Path.of(baseDir, userPath);
PathPart part = new PathPart(requested, 0, Files.size(requested));
// after
Path requested = Path.of(baseDir, userPath).normalize();
if (!requested.startsWith(baseDir) || !Files.isRegularFile(requested)) {
return Response.status(Response.Status.NOT_FOUND).build();
}
PathPart part = new PathPart(requested, 0, Files.size(requested)); Defensive patterns
Strategy: validation
Validate before calling
if (file == null || !Files.isRegularFile(file)) {
return Response.status(Response.Status.NOT_FOUND).build();
} Type guard
boolean isRegularFile(Path p) {
return p != null && Files.isRegularFile(p);
} Try / catch
try {
return Response.ok(new PathPart(file, offset, count)).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.NOT_FOUND).build();
} Prevention
- Reject directory and symlink-to-directory requests explicitly with 404.
- Normalize user paths and confine them to a base directory to avoid traversal into special files.
- Treat any user-supplied path as untrusted: check isRegularFile before serving.
When it happens
Trigger: Calling `new PathPart(file, offset, count)` with a Path that points to a directory, a device/special file, or (on some platforms) a named pipe — `Files.isRegularFile(file)` returns false.
Common situations: Serving a directory listing path passed directly to the file API; path-traversal requests that resolve to a directory or /dev/ entry; symlink targets pointing at sockets/pipes; OpenAPI/docs examples that treat an upload directory as a downloadable file.
Related errors
- File does not exist: ${file}
- File cannot be read: ${file}
- Offset + count (${offset + count}) larger than file size (${
- Path leaves the application root: <file>
- does not exist
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/2b60cfc8aed3eac7.
Report an issue: GitHub.