{"record":{"id":"5b02fea36cf3afd7","repo":"skylot/jadx","slug":"plugin-option-name-should-start-with-plugin-id","errorCode":null,"errorMessage":"Plugin option name should start with plugin id: '{}', option: {}","messagePattern":"Plugin option name should start with plugin id: '(.+?)', option: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/plugins/JadxPluginManager.java","lineNumber":197,"sourceCode":"\n\tprivate AppContext buildDefaultAppContext() {\n\t\tAppContext appContext = new AppContext();\n\t\tappContext.setGuiContext(null);\n\t\tappContext.setFilesGetter(decompiler.getArgs().getFilesGetter());\n\t\treturn appContext;\n\t}\n\n\tprivate void verifyOptions(PluginContext pluginContext, JadxPluginOptions options) {\n\t\tString pluginId = pluginContext.getPluginId();\n\t\tList<OptionDescription> descriptions = options.getOptionsDescriptions();\n\t\tif (descriptions == null) {\n\t\t\tthrow new IllegalArgumentException(\"Null option descriptions in plugin id: \" + pluginId);\n\t\t}\n\t\tString prefix = pluginId + '.';\n\t\tdescriptions.forEach(descObj -> {\n\t\t\tString optName = descObj.name();\n\t\t\tif (optName == null || !optName.startsWith(prefix)) {\n\t\t\t\tthrow new IllegalArgumentException(\"Plugin option name should start with plugin id: '\" + prefix + \"', option: \" + optName);\n\t\t\t}\n\t\t\tString desc = descObj.description();\n\t\t\tif (desc == null || desc.isEmpty()) {\n\t\t\t\tthrow new IllegalArgumentException(\"Plugin option description not set, plugin: \" + pluginId);\n\t\t\t}\n\t\t\tList<String> values = descObj.values();\n\t\t\tif (values == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"Plugin option values is null, option: \" + optName + \", plugin: \" + pluginId);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic List<JadxCodeInput> getCodeInputs() {\n\t\treturn getResolvedPluginContexts()\n\t\t\t\t.stream()\n\t\t\t\t.flatMap(p -> p.getCodeInputs().stream())\n\t\t\t\t.collect(Collectors.toList());\n\t}","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/plugins/JadxPluginManager.java#L179-L215","documentation":"Thrown as IllegalArgumentException by JadxPluginManager.verifyOptions() when an option's name() is null or does not start with the plugin ID prefix (pluginId + '.'). This naming convention prevents option-name collisions between plugins and allows the CLI/GUI to namespace options unambiguously. For a plugin with ID 'com.example.foo', every option name must begin with 'com.example.foo.'.","triggerScenarios":"A plugin's OptionDescription.name() returns a string that is null, lacks the plugin-id prefix, or uses a different separator. The manager iterates every option description after init and checks the prefix.","commonSituations":"Custom jadx plugin development where the author uses short option names (e.g. 'outputDir') instead of fully-qualified names (e.g. 'com.example.foo.outputDir'). Also triggered by copy-paste between plugins where the ID was changed but option names were not updated.","solutions":["Prefix every option name with the plugin ID followed by a dot: '<pluginId>.<optionName>'.","Use the plugin's getPluginId() return value dynamically rather than hardcoding, to avoid mismatches after ID changes.","Check for null option names in your OptionDescription implementation.","Report or fix the plugin if you are not its author."],"exampleFix":"// before\nnew OptionDescription() {\n    public String name() { return \"outputDir\"; } // missing prefix\n    ...\n}\n\n// after\nnew OptionDescription() {\n    public String name() { return pluginId + \".outputDir\"; }\n    ...\n}","handlingStrategy":"validation","validationCode":"// Build option names with the plugin ID prefix\nString prefix = pluginId + '.';\nString fullName = prefix + \"outputDir\"; // e.g. \"com.example.foo.outputDir\"\n// Verify before returning\nassert fullName.startsWith(prefix);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Plugin authors: prefix every option name with '<pluginId>.'.","Derive the prefix from getPluginId() at runtime rather than hardcoding to avoid mismatches after renames.","Add a unit test asserting all option names start with the plugin ID."],"tags":["jadx","plugins","options","naming-convention","plugin-contract","illegal-argument"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}