quarkusio/quarkus · error · IllegalStateException
Must launch jlink image in module mode only
Error message
Must launch jlink image in module mode only
What it means
JLinkAppLauncher.run asserts the launcher class was loaded as part of a named Module (module mode). When Class.getModule() returns null (or the unnamed module scenario the code treats as absence), the jlink image is being launched outside module mode, which this launcher does not support. The launcher relies on the module layer to load application modules.
Source
Thrown at extensions/packaging/jlink/launcher/src/main/java/io/quarkus/jlink/launcher/JLinkAppLauncher.java:28
import io.smallrye.modules.ModuleFinder;
import io.smallrye.modules.ModuleLoader;
/**
* The application launcher for a jlink'd module application.
*/
public final class JLinkAppLauncher {
private JLinkAppLauncher() {
}
/**
* Launch the application.
*
* @param args the application arguments
*/
public static void run(String appModule, String[] args) {
Module myModule = JLinkAppLauncher.class.getModule();
if (myModule == null) {
throw new IllegalStateException("Must launch jlink image in module mode only");
}
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();View on GitHub (pinned to e1c734241f)
Solutions
- Launch via the generated image launcher script (image/bin/<name>) rather than java -cp
- Ensure the main class and module-info are on the module path with `-m <module>/<mainclass>`
- Do not extract/repackage the jlink image into a flat classpath jar
- Regenerate the image with the jlink packaging extension if launcher scripts were modified
Example fix
// before: runs in classpath (unnamed module) mode java -cp image/app.jar com.example.Main // after: module mode via launcher script or -m image/bin/myapp // or: java -m com.example/com.example.Main
Defensive patterns
Strategy: validation
Validate before calling
// ensure module mode before launching
Module m = JLinkAppLauncher.class.getModule();
if (m == null || m.getLayer() == null) {
throw new IllegalStateException("JLink launcher must run in module mode; use image/bin/<launcher>");
} Type guard
boolean runsInModuleMode(Class<?> c) {
Module m = c.getModule();
return m != null && m.isNamed() && m.getLayer() != null;
} Try / catch
try {
JLinkAppLauncher.run(appModule, args);
} catch (IllegalStateException e) {
if (e.getMessage().contains("module mode")) {
System.err.println("Launch via the image launcher script, not the classpath");
}
throw e;
} Prevention
- Always start the app via the generated image/bin/<name> script
- Never repackage the image into a flat classpath fat jar
- Keep module-info.class in the image artifacts
When it happens
Trigger: Running the generated main class from the classpath instead of via the module-path launcher; running the launcher in an environment without a module system context (e.g. reflective/flat classpath execution).
Common situations: Launching the image's main class directly with `java -cp` instead of the generated `bin/<launcher>` script; repackaging the application as a fat jar and running it; test harnesses loading the class off the classpath.
Related errors
- Module of jlink image launcher is not in a module layer
- Cannot determine image path (bin path)
- Cannot determine image path (image path)
- Application module not found
- You're not expected to use the unnamed module as identifier
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/3904a6db647f8502.
Report an issue: GitHub.