{"record":{"id":"7ce9e42d835981e4","repo":"Konloch/bytecode-viewer","slug":"multiple-plugin-subclasses","errorCode":null,"errorMessage":"Multiple plugin subclasses.","messagePattern":"Multiple plugin subclasses\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/main/java/the/bytecode/club/bytecodeviewer/plugin/strategies/CompiledJavaPluginLaunchStrategy.java","lineNumber":61,"sourceCode":"    private static final String PLUGIN_CLASS_NAME = Plugin.class.getCanonicalName().replace(\".\", \"/\");\n\n    private final Set<LoadedPluginData> loaded = new HashSet<>();\n\n    @Override\n    public Plugin run(File file) throws Throwable\n    {\n        Set<LoadedNodeData> set = loadData(file);\n\n        LoadedNodeData pdata = null;\n        for (LoadedNodeData d : set)\n        {\n            ClassNode cn = d.node;\n            if (Objects.equals(cn.superName, PLUGIN_CLASS_NAME))\n            {\n                if (pdata == null)\n                    pdata = d;\n                else\n                    throw new RuntimeException(\"Multiple plugin subclasses.\");\n            }\n        }\n\n        LoadingClassLoader cl = new LoadingClassLoader(pdata, set);\n        Plugin p = cl.pluginKlass.getDeclaredConstructor().newInstance();\n        LoadedPluginData npdata = new LoadedPluginData(pdata, cl, p);\n        loaded.add(npdata);\n\n        return p;\n    }\n\n    public Set<LoadedPluginData> getLoaded()\n    {\n        return loaded;\n    }\n\n    private static Set<LoadedNodeData> loadData(File jarFile) throws Throwable\n    {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/Konloch/bytecode-viewer/blob/31430e0033fa220db566b5ef461256727ff6793b/src/main/java/the/bytecode/club/bytecodeviewer/plugin/strategies/CompiledJavaPluginLaunchStrategy.java#L43-L79","documentation":"CompiledJavaPluginLaunchStrategy.run loads classes from the compiled plugin bundle and scans ClassNodes for exactly one subclass of Plugin (PLUGIN_CLASS_NAME). If two or more classes extend Plugin it cannot pick which to instantiate and throws RuntimeException(\"Multiple plugin subclasses.\").","triggerScenarios":"Running a compiled Java plugin whose class set contains two or more classes whose superName equals PLUGIN_CLASS_NAME — e.g. several plugin classes bundled into one plugin file.","commonSituations":"Bundling multiple plugins into a single compiled plugin archive; leftover old plugin classes not removed from the build; an inner/helper class accidentally extending Plugin; recompiling into the same output directory merging old classes.","solutions":["Ensure exactly one class extends Plugin in the plugin bundle; remove or split the others.","Clean the build output and recompile so stale classes are not bundled.","Split each plugin class into its own plugin file and run them separately.","Convert extra classes to not extend Plugin (use plain helpers)."],"exampleFix":"// before\nclass MyPlugin extends Plugin { ... }\nclass MyOtherPlugin extends Plugin { ... } // bundled together -> throws\n// after\nclass MyPlugin extends Plugin { ... }\nclass MyHelper { ... } // only one Plugin subclass in the bundle","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    PluginManager.runPlugin(compiledPluginFile);\n} catch (RuntimeException e) {\n    if (\"Multiple plugin subclasses.\".equals(e.getMessage()))\n        showError(\"Bundle contains more than one Plugin subclass; split or clean the plugin.\");\n    else\n        throw e;\n}","preventionTips":["Keep one Plugin subclass per plugin bundle.","Clean build output before recompiling to avoid stale classes.","Make helper classes plain (do not extend Plugin).","Inspect the bundled classes (e.g. in Bytecode Viewer) before distributing."],"tags":["plugin-system","classpath","ambiguous-class","compiled-java"],"backgroundTag":"multiple-plugin-subclasses","analyzedSha":"31430e0033fa220db566b5ef461256727ff6793b","analyzedAt":"2026-09-05T18:22:22.725Z","contentChangedAt":"2026-09-05T18:22:22.725Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}