{"record":{"id":"3904a6db647f8502","repo":"quarkusio/quarkus","slug":"must-launch-jlink-image-in-module-mode-only","errorCode":null,"errorMessage":"Must launch jlink image in module mode only","messagePattern":"Must launch jlink image in module mode only","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/packaging/jlink/launcher/src/main/java/io/quarkus/jlink/launcher/JLinkAppLauncher.java","lineNumber":28,"sourceCode":"import io.smallrye.modules.ModuleFinder;\nimport io.smallrye.modules.ModuleLoader;\n\n/**\n * The application launcher for a jlink'd module application.\n */\npublic final class JLinkAppLauncher {\n    private JLinkAppLauncher() {\n    }\n\n    /**\n     * Launch the application.\n     *\n     * @param args the application arguments\n     */\n    public static void run(String appModule, String[] args) {\n        Module myModule = JLinkAppLauncher.class.getModule();\n        if (myModule == null) {\n            throw new IllegalStateException(\"Must launch jlink image in module mode only\");\n        }\n        ModuleLayer myLayer = myModule.getLayer();\n        if (myLayer == null) {\n            throw new IllegalStateException(\"Module of jlink image launcher is not in a module layer\");\n        }\n\n        @SuppressWarnings(\"resource\")\n        ModuleLoader base = ModuleLoader.forLayer(\"base\", myLayer);\n\n        // try to ascertain our own path\n        String cmd = ProcessHandle.current().info().command()\n                .orElseThrow(() -> new IllegalStateException(\"Cannot determine image path (ProcessHandle)\"));\n        Path cmdPath = Path.of(cmd);\n        Path binPath = cmdPath.getParent();\n        if (binPath == null || !binPath.getFileName().toString().equals(\"bin\")) {\n            throw new IllegalStateException(\"Cannot determine image path (bin path)\");\n        }\n        Path imagePath = binPath.getParent();","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/packaging/jlink/launcher/src/main/java/io/quarkus/jlink/launcher/JLinkAppLauncher.java#L10-L46","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before: runs in classpath (unnamed module) mode\njava -cp image/app.jar com.example.Main\n// after: module mode via launcher script or -m\nimage/bin/myapp\n// or: java -m com.example/com.example.Main","handlingStrategy":"validation","validationCode":"// ensure module mode before launching\nModule m = JLinkAppLauncher.class.getModule();\nif (m == null || m.getLayer() == null) {\n    throw new IllegalStateException(\"JLink launcher must run in module mode; use image/bin/<launcher>\");\n}","typeGuard":"boolean runsInModuleMode(Class<?> c) {\n    Module m = c.getModule();\n    return m != null && m.isNamed() && m.getLayer() != null;\n}","tryCatchPattern":"try {\n    JLinkAppLauncher.run(appModule, args);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"module mode\")) {\n        System.err.println(\"Launch via the image launcher script, not the classpath\");\n    }\n    throw e;\n}","preventionTips":["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"],"tags":["jlink","jpms","launcher"],"backgroundTag":"jpms-module-mode-required","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}