quarkusio/quarkus · error · IllegalArgumentException

File cannot be read: ${file}

Error message

File cannot be read: ${file}

What it means

PathPart requires the file to be readable by the current process so the response can stream its bytes. This IllegalArgumentException is thrown when the file exists and is a regular file but the JVM lacks read permission (POSIX permissions, ACLs, or sandbox/SELinux restrictions).

Source

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

    /**
     * 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

  1. Fix file permissions/ownership so the Quarkus process user can read the file (chmod/chown or correct volume securityContext).
  2. Check `Files.isReadable(file)` before constructing PathPart and return 403 to the client if not readable.
  3. Run the container with the same user/uid that owns the file, or write served files with world/group-readable permissions at creation time.
  4. Inspect denial logs (SELinux audit, container runtime) if permissions look correct but reads still fail.

Example fix

// before
Path file = Path.of(uploadsDir, id);
return Response.ok(new PathPart(file, 0, Files.size(file))).build();
// after
Path file = Path.of(uploadsDir, id);
if (!Files.isReadable(file)) {
    return Response.status(Response.Status.FORBIDDEN).build();
}
return Response.ok(new PathPart(file, 0, Files.size(file))).build();
Defensive patterns

Strategy: validation

Validate before calling

if (!Files.isReadable(file)) {
    return Response.status(Response.Status.FORBIDDEN).build();
}

Type guard

boolean isReadableFile(Path p) {
    return p != null && Files.isRegularFile(p) && Files.isReadable(p);
}

Try / catch

try {
    return Response.ok(new PathPart(file, 0, Files.size(file))).build();
} catch (IllegalArgumentException e) {
    LOG.errorf("Cannot serve unreadable file %s", file);
    return Response.status(Response.Status.FORBIDDEN).build();
}

Prevention

When it happens

Trigger: Calling `new PathPart(file, offset, count)` where `Files.isReadable(file)` is false — e.g. file owned by another user with 0600 permissions, or the container runs as a non-root user without access to a mounted volume file.

Common situations: Files written by root on a shared volume but served by a container running as user 1001; strict umask after processing uploads; read-only mounted secret files with wrong ownership; SELinux/AppArmor denials in hardened deployments.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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