{"record":{"id":"a9b08193a085e6ac","repo":"skylot/jadx","slug":"parse-failed-for-option-option-name-value","errorCode":null,"errorMessage":"Parse failed for option: ${option.name}, value: ${value}","messagePattern":"Parse failed for option: (.+?), value: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/api/plugins/options/impl/BasePluginOptionsBuilder.java","lineNumber":104,"sourceCode":"\t\tfor (OptionData<?> option : options) {\n\t\t\tparseOption(option, map.get(option.name));\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<OptionDescription> getOptionsDescriptions() {\n\t\treturn Collections.unmodifiableList(options);\n\t}\n\n\tprivate static <T> void parseOption(OptionData<T> option, @Nullable String value) {\n\t\tT parsedValue;\n\t\tif (value == null) {\n\t\t\tparsedValue = option.defaultValue;\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tparsedValue = option.getParser().apply(value);\n\t\t\t} catch (Exception e) {\n\t\t\t\tthrow new RuntimeException(\"Parse failed for option: \" + option.name + \", value: \" + value, e);\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\toption.getSetter().accept(parsedValue);\n\t\t} catch (Exception e) {\n\t\t\tthrow new RuntimeException(\"Setter invoke failed for option: \" + option.name + \", value: \" + parsedValue, e);\n\t\t}\n\t}\n\n\tprivate static boolean parseBoolOption(String name, String val) {\n\t\tString valLower = val.trim().toLowerCase(Locale.ROOT);\n\t\tif (valLower.equals(\"yes\") || valLower.equals(\"true\")) {\n\t\t\treturn true;\n\t\t}\n\t\tif (valLower.equals(\"no\") || valLower.equals(\"false\")) {\n\t\t\treturn false;\n\t\t}\n\t\tthrow new IllegalArgumentException(\"Unknown value '\" + val + \"' for option '\" + name + \"', expect: 'yes' or 'no'\");","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/api/plugins/options/impl/BasePluginOptionsBuilder.java#L86-L122","documentation":"Thrown by BasePluginOptionsBuilder.parseOption when the registered parser function for a plugin option throws any exception while converting the user-supplied string value. Jadx wraps the original exception in a RuntimeException so the plugin options builder can uniformly report parse failures with the option name and raw value. The cause chain preserves the underlying exception (e.g., NumberFormatException from Integer::parseInt).","triggerScenarios":"A plugin registers an option via intOption(name) (whose parser is Integer::parseInt) and the user supplies a non-numeric string. Or a custom OptionBuilder.parser(Function) lambda throws on malformed input. The error fires inside setOptions(map) -> parseOption(option, value) when option.getParser().apply(value) raises.","commonSituations":"User passes --plugin-option myplugin.depth=abc to an integer option. A enumOption parser receives a value that does not match any enum constant (the valueOf call throws IllegalArgumentException). Locale-specific parsing (e.g., decimal separators) in a custom parser fails on unexpected input.","solutions":["Check the option's declared type and values (via getOptionsDescriptions) and supply a value that the option's parser accepts.","For integer options, ensure the value is a valid base-10 integer with no surrounding text.","For enum options, pass one of the documented enum constant names (case is handled by the default enumOption parser, but verify the specific plugin).","If writing the plugin, make the custom parser more lenient or throw a descriptive IllegalArgumentException so the wrapped message is clear."],"exampleFix":"// before\noption(\"depth\").parser(Integer::parseInt)\n// invoked with: myplugin.depth=12x\n\n// after (user fix): supply a valid integer\n// myplugin.depth=12\n\n// after (plugin author fix): validate before parse\noption(\"depth\").parser(s -> {\n    try { return Integer.parseInt(s.trim()); }\n    catch (NumberFormatException e) {\n        throw new IllegalArgumentException(\"depth must be an integer, got: \" + s);\n    }\n})","handlingStrategy":"validation","validationCode":"// Check option description before parsing to validate user input\nList<OptionDescription> descs = optionsBuilder.getOptionsDescriptions();\nfor (OptionDescription desc : descs) {\n    if (desc.getName().equals(optionName)) {\n        // For numeric options, verify the value is parseable\n        if (desc.getType() == OptionType.NUMBER) {\n            try { Integer.parseInt(userValue); }\n            catch (NumberFormatException e) {\n                throw new IllegalArgumentException(optionName + \" requires an integer\");\n            }\n        }\n    }\n}","typeGuard":"static boolean optionValueIsParsable(OptionDescription desc, String value) {\n    if (value == null) return true;\n    switch (desc.getType()) {\n        case NUMBER:\n            return value.matches(\"-?\\\\d+\");\n        case BOOLEAN:\n            String lower = value.trim().toLowerCase(Locale.ROOT);\n            return lower.equals(\"yes\") || lower.equals(\"no\")\n                || lower.equals(\"true\") || lower.equals(\"false\");\n        case STRING:\n        default:\n            return true;\n    }\n}","tryCatchPattern":"try {\n    optionsBuilder.setOptions(userOptionsMap);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Parse failed for option:\")) {\n        LOG.error(\"Invalid option value: {}\", e.getMessage());\n    } else {\n        throw e;\n    }\n}","preventionTips":["Validate option values against their declared OptionType before calling setOptions.","For enum options, check the value against the declared values list in OptionDescription.","When building a custom parser, throw IllegalArgumentException with a human-readable message so the wrapped RuntimeException is clear."],"tags":["options","plugin","parse","validation"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}