quarkusio/quarkus · error · java.lang.IllegalArgumentException

Expected a path relative to the root of the path tree but go

Error message

Expected a path relative to the root of the path tree but got 

What it means

PathTreeVisit.ensureResourcePath() rejects resource paths that are absolute, since lookups must be relative to the path tree root. It throws IllegalArgumentException 'Expected a path relative to the root of the path tree but got <path>' when the string is a Unix absolute path (leading '/') or a Windows absolute path (drive letter or UNC), or starts with the default separator.

Source

Thrown at independent-projects/bootstrap/app-model/src/main/java/io/quarkus/paths/PathTreeVisit.java:38

    private static volatile Pattern windowsAbsolutePathPattern;

    private static Pattern windowsAbsolutePathPattern() {
        return windowsAbsolutePathPattern == null ? windowsAbsolutePathPattern = Pattern.compile("[a-zA-Z]:\\\\.*")
                : windowsAbsolutePathPattern;
    }

    static boolean isAbsolutePath(String path) {
        return path != null && !path.isEmpty()
                && (path.charAt(0) == '/' // we want to check for '/' on every OS
                        || USE_WINDOWS_ABSOLUTE_PATH_PATTERN
                                && (windowsAbsolutePathPattern().matcher(path).matches())
                        || path.startsWith(FileSystems.getDefault().getSeparator()));
    }

    static void ensureResourcePath(FileSystem fs, String path) {
        if (isAbsolutePath(path)) {
            throw new IllegalArgumentException("Expected a path relative to the root of the path tree but got " + path);
        }
        // this is to disallow reading outside the path tree root
        if (path != null && path.contains("..")) {
            for (Path pathElement : fs.getPath(path)) {
                if (pathElement.toString().equals("..")) {
                    throw new IllegalArgumentException("'..' cannot be used in resource paths, but got " + path);
                }
            }
        }
    }

    static String resourceNameToFsPath(String resourceName, FileSystem fs) {
        return fs.getSeparator().equals("/") ? resourceName : resourceName.replace("/", fs.getSeparator());
    }

    static void walk(Path root, Path rootDir, Path walkDir, PathFilter pathFilter, Map<String, String> multiReleaseMapping,
            PathVisitor visitor) {
        final PathTreeVisit visit = new PathTreeVisit(root, rootDir, pathFilter, multiReleaseMapping);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Strip the leading root/separator before lookup: convert absolute paths to relative via rootPath.relativize(p).toString().
  2. Normalize manually: remove a leading '/' (or drive prefix) with something like path.startsWith("/") ? path.substring(1) : path.
  3. Never pass values from getAbsolutePath()/Path.toString() of absolute paths into resource lookups; keep resource names as symbolic relative strings.
  4. Catch IllegalArgumentException and log the offending path to quickly identify the producer of absolute paths.

Example fix

// before
Path resource = tree.getPath("/config/app.properties"); // IllegalArgumentException
// after
String rel = "/config/app.properties";
if (rel.startsWith("/")) {
    rel = rel.substring(1);
}
Path resource = tree.getPath(rel);
Defensive patterns

Strategy: validation

Validate before calling

static String toRelativeResourcePath(String path) {
    if (path.startsWith("/") || path.startsWith("\\") || (path.length() > 1 && path.charAt(1) == ':')) {
        throw new IllegalArgumentException("Resource path must be relative: " + path);
    }
    return path;
}

Type guard

static boolean isRelativeResourcePath(String path) {
    if (path == null || path.isEmpty()) return false;
    if (path.startsWith("/") || path.startsWith("\\")) return false;
    if (path.length() > 1 && path.charAt(1) == ':') return false; // Windows drive
    return true;
}

Try / catch

try {
    tree.apply(visit, resourcePath);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Expected a path relative")) {
        String rel = resourcePath.replaceFirst("^/", "");
        tree.apply(visit, rel);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling lookup/apply/walk APIs (e.g. PathTree.apply or PathTreeWalk) with a path string like '/foo/bar.txt' or 'C:\\data\\x.txt'; concatenating a root path with a resource name and passing the result; copying code that used File.getAbsolutePath().

Common situations: Mistakenly passing absolute paths obtained from config or from Path.toString() of an absolute file; Windows-specific absolute paths surfacing on path joins; porting code from java.io.File to resource lookup.

Related errors


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