{"record":{"id":"338e40e220c8af31","repo":"skylot/jadx","slug":"setter-invoke-failed-for-option-option-name-v","errorCode":null,"errorMessage":"Setter invoke failed for option: ${option.name}, value: ${parsedValue}","messagePattern":"Setter invoke 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":110,"sourceCode":"\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'\");\n\t}\n\n\tprivate <T> OptionBuilder<T> addOption(OptionBuilder<T> optionData) {\n\t\tthis.options.add((OptionData<?>) optionData);\n\t\treturn optionData;\n\t}","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/api/plugins/options/impl/BasePluginOptionsBuilder.java#L92-L128","documentation":"Thrown by BasePluginOptionsBuilder.parseOption when the setter Consumer (the field-assignment lambda) for a parsed option value raises an exception. Jadx catches any exception from option.getSetter().accept(parsedValue) and re-throws it as a RuntimeException with the option name and the already-parsed value. This distinguishes setter-time failures from parse-time failures (error 41).","triggerScenarios":"A plugin registers an option whose setter lambda (via OptionBuilder.setter(Consumer)) performs additional validation or side-effects and throws. For example, a setter that rejects null, validates a range, or calls a method that fails. The trigger is that parsing succeeded but assignment did not.","commonSituations":"A custom setter validates constraints (e.g., rejects a port number < 1024) and throws. A setter writes to a collection or object that is in an invalid state. A nullable handling mismatch where the default value is null but the setter expects non-null. Typically a plugin-internal programming error rather than user input error.","solutions":["Inspect the cause exception in the stack trace to identify which constraint in the setter lambda failed.","If the setter validates ranges or formats, adjust the option value to satisfy the constraint.","If writing the plugin, separate validation from the setter — validate in the parser instead, or catch expected conditions in the setter and rethrow with a clear message.","Ensure the setter handles the option's defaultValue gracefully when the user omits the option (value == null path yields defaultValue)."],"exampleFix":"// before (plugin setter with implicit constraint)\n.option(\"port\")\n    .setter(v -> { if (v < 1024) throw new IllegalArgumentException(\"port too low\"); this.port = v; })\n// invoked with myplugin.port=80 → triggers 'Setter invoke failed'\n\n// after: supply a privileged port value\n// myplugin.port=8080","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    optionsBuilder.setOptions(userOptionsMap);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Setter invoke failed for option:\")) {\n        // The parsed value was valid but the setter rejected it\n        LOG.warn(\"Option setter rejected value: {}\", e.getMessage(), e);\n    } else {\n        throw e; // not a setter failure, rethrow\n    }\n}","preventionTips":["When writing a plugin setter, keep it simple — assign the value without side-effects that can throw.","Move validation logic into the parser, not the setter, so failures surface as parse errors with clearer messages.","Handle the option's defaultValue gracefully in the setter when the user omits the option."],"tags":["options","plugin","setter","validation"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}