quarkusio/quarkus · error · IllegalStateException

Cannot determine image path (image path)

Error message

Cannot determine image path (image path)

What it means

Immediately after resolving the bin directory, the launcher takes its parent as the image root. If binPath.getParent() returns null (bin is a filesystem root), the image path cannot be determined and the launcher aborts. A sibling error 'Cannot determine image path (bin path)' covers the case where the parent isn't named 'bin'.

Source

Thrown at extensions/packaging/jlink/launcher/src/main/java/io/quarkus/jlink/launcher/JLinkAppLauncher.java:48

        ModuleLayer myLayer = myModule.getLayer();
        if (myLayer == null) {
            throw new IllegalStateException("Module of jlink image launcher is not in a module layer");
        }

        @SuppressWarnings("resource")
        ModuleLoader base = ModuleLoader.forLayer("base", myLayer);

        // try to ascertain our own path
        String cmd = ProcessHandle.current().info().command()
                .orElseThrow(() -> new IllegalStateException("Cannot determine image path (ProcessHandle)"));
        Path cmdPath = Path.of(cmd);
        Path binPath = cmdPath.getParent();
        if (binPath == null || !binPath.getFileName().toString().equals("bin")) {
            throw new IllegalStateException("Cannot determine image path (bin path)");
        }
        Path imagePath = binPath.getParent();
        if (imagePath == null) {
            throw new IllegalStateException("Cannot determine image path (image path)");
        }

        Path libPath = imagePath.resolve("lib").resolve("quarkus");

        // create a layer for our dynamic modules
        ModuleLoader dyn = new ModuleLoader("dyn", ModuleFinder.fromFileSystem(List.of(libPath))) {
            public LoadedModule loadModule(final String moduleName) {
                LoadedModule found = base.loadModule(moduleName);
                if (found == null) {
                    found = super.loadModule(moduleName);
                }
                return found;
            }
        };

        // load the application
        LoadedModule loadedModule = dyn.loadModule(appModule);
        if (loadedModule == null) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Restore the standard image layout so the launcher lives at <image>/bin/<name> with a non-root parent
  2. Run from an installed image directory, not a chroot/mount where bin is the filesystem root
  3. Regenerate the jlink image with the Quarkus jlink packaging extension

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

Path binPath = Path.of(
        ProcessHandle.current().info().command().orElseThrow()).getParent();
if (binPath == null || binPath.getParent() == null) {
    throw new IllegalStateException("bin directory has no parent; invalid image layout");
}

Type guard

boolean hasImageRoot(Path binDir) {
    return binDir.getParent() != null;
}

Try / catch

try {
    JLinkAppLauncher.run(appModule, args);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("image path")) {
        throw new IllegalStateException("Image layout invalid; regenerate the image", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: The launcher executable sits directly at a filesystem root (its bin directory has no parent) — an essentially impossible layout for a real jlink image.

Common situations: Highly contrived setups where the executable is mounted/chrooted at /bin of a root namespace or a sandbox flattens the image layout to the root.

Related errors


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