quarkusio/quarkus · error · IllegalArgumentException

Path leaves the application root: <file>

Error message

Path leaves the application root: <file>

What it means

During validation, if a path component exists and its real path does not start with the real application root, the resolved path is judged to escape the root via a real-path alias (e.g. a bind mount or hard link to outside), and this IllegalArgumentException is thrown. It complements the lexical .. check by catching physical escapes.

Source

Thrown at core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java:487

    }

    private static void validateExistingPathComponents(Path normalizedRoot, Path resolved, String file) {
        final Path realRoot;
        try {
            realRoot = normalizedRoot.toRealPath();
        } catch (IOException e) {
            throw new IllegalArgumentException("Unable to validate the application root for remote-dev path: " + file, e);
        }
        Path current = normalizedRoot;
        for (Path element : normalizedRoot.relativize(resolved)) {
            current = current.resolve(element);
            if (Files.isSymbolicLink(current)) {
                throw new IllegalArgumentException("Symbolic links are not allowed in remote-dev paths: " + file);
            }
            if (Files.exists(current, LinkOption.NOFOLLOW_LINKS)) {
                try {
                    if (!current.toRealPath().startsWith(realRoot)) {
                        throw new IllegalArgumentException("Path leaves the application root: " + file);
                    }
                } catch (IOException e) {
                    throw new IllegalArgumentException("Unable to validate remote-dev path: " + file, e);
                }
            } else {
                break;
            }
        }
    }

    private static String normalizeFile(String file) {
        requireNonNull(file, "file");
        file = file.replace('\\', '/');
        if (file.startsWith("/")) {
            file = file.substring(1);
        }
        return file;
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure all paths under the application root are physically inside it (no nested bind mounts for the sync path).
  2. Use consistent canonical paths when mounting volumes into dev containers.
  3. Move the synced output directory so its real path is within the root.
  4. Run remote-dev server and client against the same canonical filesystem layout.

Example fix

# before: docker -v /elsewhere/classes:/app/target/classes (real path leaves root)
# after: build into a directory physically under the app root, no nested bind mount
Defensive patterns

Strategy: validation

Validate before calling

Path root = Path.of(".").toAbsolutePath().normalize().toRealPath();
Path target = root.resolve(relPath).normalize();
if (Files.exists(target, LinkOption.NOFOLLOW_LINKS) && !target.toRealPath().startsWith(root))
    throw new IllegalStateException("target real path escapes root: " + target);

Try / catch

try {
    client.sync(path);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Path leaves the application root")) {
        log.errorf("%s resolves outside the app root (bind mount or link) — fix mounts", path);
    } else throw e;
}

Prevention

When it happens

Trigger: updateFile or resolveApplicationPath where an existing component of the path resolves (via toRealPath) outside the real application root — bind mounts, mounts overlapping the root, or links resolved by the OS.

Common situations: Application root contains an overlay/bind-mounted subdirectory; Docker volume mounts nested inside the project dir; network mounts aliased under a different canonical path.

Related errors


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