{"record":{"id":"9e8660b67d69e408","repo":"quarkusio/quarkus","slug":"expected-a-path-relative-to-the-root-of-the-path-t","errorCode":null,"errorMessage":"Expected a path relative to the root of the path tree but got ","messagePattern":"Expected a path relative to the root of the path tree but got ","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"independent-projects/bootstrap/app-model/src/main/java/io/quarkus/paths/PathTreeVisit.java","lineNumber":38,"sourceCode":"\n    private static volatile Pattern windowsAbsolutePathPattern;\n\n    private static Pattern windowsAbsolutePathPattern() {\n        return windowsAbsolutePathPattern == null ? windowsAbsolutePathPattern = Pattern.compile(\"[a-zA-Z]:\\\\\\\\.*\")\n                : windowsAbsolutePathPattern;\n    }\n\n    static boolean isAbsolutePath(String path) {\n        return path != null && !path.isEmpty()\n                && (path.charAt(0) == '/' // we want to check for '/' on every OS\n                        || USE_WINDOWS_ABSOLUTE_PATH_PATTERN\n                                && (windowsAbsolutePathPattern().matcher(path).matches())\n                        || path.startsWith(FileSystems.getDefault().getSeparator()));\n    }\n\n    static void ensureResourcePath(FileSystem fs, String path) {\n        if (isAbsolutePath(path)) {\n            throw new IllegalArgumentException(\"Expected a path relative to the root of the path tree but got \" + path);\n        }\n        // this is to disallow reading outside the path tree root\n        if (path != null && path.contains(\"..\")) {\n            for (Path pathElement : fs.getPath(path)) {\n                if (pathElement.toString().equals(\"..\")) {\n                    throw new IllegalArgumentException(\"'..' cannot be used in resource paths, but got \" + path);\n                }\n            }\n        }\n    }\n\n    static String resourceNameToFsPath(String resourceName, FileSystem fs) {\n        return fs.getSeparator().equals(\"/\") ? resourceName : resourceName.replace(\"/\", fs.getSeparator());\n    }\n\n    static void walk(Path root, Path rootDir, Path walkDir, PathFilter pathFilter, Map<String, String> multiReleaseMapping,\n            PathVisitor visitor) {\n        final PathTreeVisit visit = new PathTreeVisit(root, rootDir, pathFilter, multiReleaseMapping);","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/paths/PathTreeVisit.java#L20-L56","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","solutions":["Strip the leading root/separator before lookup: convert absolute paths to relative via rootPath.relativize(p).toString().","Normalize manually: remove a leading '/' (or drive prefix) with something like path.startsWith(\"/\") ? path.substring(1) : path.","Never pass values from getAbsolutePath()/Path.toString() of absolute paths into resource lookups; keep resource names as symbolic relative strings.","Catch IllegalArgumentException and log the offending path to quickly identify the producer of absolute paths."],"exampleFix":"// before\nPath resource = tree.getPath(\"/config/app.properties\"); // IllegalArgumentException\n// after\nString rel = \"/config/app.properties\";\nif (rel.startsWith(\"/\")) {\n    rel = rel.substring(1);\n}\nPath resource = tree.getPath(rel);","handlingStrategy":"validation","validationCode":"static String toRelativeResourcePath(String path) {\n    if (path.startsWith(\"/\") || path.startsWith(\"\\\\\") || (path.length() > 1 && path.charAt(1) == ':')) {\n        throw new IllegalArgumentException(\"Resource path must be relative: \" + path);\n    }\n    return path;\n}","typeGuard":"static boolean isRelativeResourcePath(String path) {\n    if (path == null || path.isEmpty()) return false;\n    if (path.startsWith(\"/\") || path.startsWith(\"\\\\\")) return false;\n    if (path.length() > 1 && path.charAt(1) == ':') return false; // Windows drive\n    return true;\n}","tryCatchPattern":"try {\n    tree.apply(visit, resourcePath);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Expected a path relative\")) {\n        String rel = resourcePath.replaceFirst(\"^/\", \"\");\n        tree.apply(visit, rel);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Never pass File.getAbsolutePath()/absolute Path.toString() results into resource lookups.","Keep resource names as constant relative strings (\"config/app.properties\").","Strip leading separators when a path may come from user config.","Also avoid '..' segments — ensureResourcePath rejects them separately."],"tags":["illegal-argument","path-handling","quarkus-paths","resource-lookup"],"backgroundTag":"absolute-path-not-allowed","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"}