{"record":{"id":"bc955c25058dfe08","repo":"quarkusio/quarkus","slug":"module-of-jlink-image-launcher-is-not-in-a-module","errorCode":null,"errorMessage":"Module of jlink image launcher is not in a module layer","messagePattern":"Module of jlink image launcher is not in a module layer","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/packaging/jlink/launcher/src/main/java/io/quarkus/jlink/launcher/JLinkAppLauncher.java","lineNumber":32,"sourceCode":" * 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();\n        if (imagePath == null) {\n            throw new IllegalStateException(\"Cannot determine image path (image path)\");\n        }\n","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/packaging/jlink/launcher/src/main/java/io/quarkus/jlink/launcher/JLinkAppLauncher.java#L14-L50","documentation":"After confirming module mode, JLinkAppLauncher.run retrieves the ModuleLayer of the launcher's module via myModule.getLayer(). A null layer means the module was defined but not bound to any module layer (e.g. loaded reflectively or via a non-standard boot), so ModuleLoader.forLayer cannot enumerate/load modules and the launcher aborts.","triggerScenarios":"The launcher class's module has no associated ModuleLayer — typically when the class is loaded by a custom/reflective loader without layer definition, or before/atypical layer bootstrapping.","commonSituations":"Embedding the launcher class in a custom framework that defines modules without layers; exotic classloading setups in test harnesses; launching with instrumentation agents that redefine module loading.","solutions":["Launch the application normally through the generated jlink image launcher so the boot layer contains the launcher module","Do not load JLinkAppLauncher via reflection or custom classloaders outside a ModuleLayer","Check for agents/tools that redefine modules and disable them for the launcher","Verify the JVM is started normally (boot layer intact), not via low-level ModuleLayer APIs"],"exampleFix":"// before: reflective load breaks layer binding\nClass.forName(\"io.quarkus.jlink.launcher.JLinkAppLauncher\")\n// after: exec the image launcher\nProcess p = new ProcessBuilder(\"image/bin/myapp\").start();","handlingStrategy":"type-guard","validationCode":"Module m = JLinkAppLauncher.class.getModule();\nif (m == null || m.getLayer() == null) {\n    throw new IllegalStateException(\"Launcher module is not bound to a ModuleLayer\");\n}","typeGuard":"boolean hasModuleLayer(Class<?> c) {\n    Module m = c.getModule();\n    return m != null && m.getLayer() != null;\n}","tryCatchPattern":"try {\n    JLinkAppLauncher.run(appModule, args);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"not in a module layer\")) {\n        throw new IllegalStateException(\"Launcher loaded outside a ModuleLayer; start the image normally\", e);\n    }\n    throw e;\n}","preventionTips":["Do not load the launcher class reflectively or via custom classloaders","Disable agents/tools that redefine module loading for the launcher JVM","Test the image launcher by executing the generated script"],"tags":["jlink","jpms","module-layer","launcher"],"backgroundTag":"module-layer-missing","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"}