{"record":{"id":"e213b34959e30537","repo":"bazelbuild/bazel","slug":"converter-s-has-d-methods-convert-string-objec","errorCode":null,"errorMessage":"Converter %s has %d methods 'convert(String, Object)', expected 1: %s","messagePattern":"Converter (.+?) has (.+?) methods 'convert\\(String, Object\\)', expected 1: (.+?)","errorType":"validation","errorClass":"OptionProcessorException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java","lineNumber":680,"sourceCode":"    DeclaredType converterType = (DeclaredType) converterElement.asType();\n    List<ExecutableElement> methodList =\n        elementUtils.getAllMembers(converterElement).stream()\n            .filter(element -> element.getKind() == ElementKind.METHOD)\n            .map(methodElement -> (ExecutableElement) methodElement)\n            .filter(methodElement -> methodElement.getSimpleName().contentEquals(\"convert\"))\n            .filter(\n                methodElement ->\n                    methodElement.getParameters().size() == 2\n                        && typeUtils.isSameType(\n                            methodElement.getParameters().get(0).asType(),\n                            elementUtils.getTypeElement(String.class.getCanonicalName()).asType())\n                        && typeUtils.isSameType(\n                            methodElement.getParameters().get(1).asType(),\n                            elementUtils.getTypeElement(Object.class.getCanonicalName()).asType()))\n            .collect(Collectors.toList());\n\n    if (methodList.size() != 1) {\n      throw new OptionProcessorException(\n          method,\n          \"Converter %s has %d methods 'convert(String, Object)', expected 1: %s\",\n          converterElement,\n          methodList.size(),\n          methodList.stream().map(Object::toString).collect(Collectors.joining(\", \")));\n    }\n\n    ExecutableType convertMethodType =\n        (ExecutableType) typeUtils.asMemberOf(converterType, methodList.get(0));\n    TypeMirror convertMethodResultType = convertMethodType.getReturnType();\n    for (TypeMirror acceptedConverterReturnType : acceptedConverterReturnTypes) {\n      if (typeUtils.isAssignable(convertMethodResultType, acceptedConverterReturnType)) {\n        return;\n      }\n    }\n    throw new OptionProcessorException(\n        method,\n        \"Type of field (%s) must be assignable from the converter's return type (%s)\",","sourceCodeStart":662,"sourceCodeEnd":698,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java#L662-L698","documentation":"Bazel's options annotation processor requires that a supplied converter class expose exactly one method named convert taking exactly (String, Object). This error fires when zero or multiple matching overloads are found — the processor could not unambiguously locate the conversion entry point.","triggerScenarios":"A converter class that lacks a public convert(String, Object) method (wrong parameter types, single-argument convert(String), or the method lives only in a sibling class), or that declares several 2-arg overloads of convert with first param String and second param Object (e.g. via overloaded signatures in generic hierarchies).","commonSituations":"Implementing the Converter interface incorrectly (custom convert(String) instead of the interface's convert(String, Object)); adding convenience overloads that also match the (String, Object) shape; bridging/inheritance producing duplicate resolved signatures; forgetting to implement the interface at all and relying on a differently-named method.","solutions":["Make the converter implement com.google.devtools.common.options.Converter and override exactly one public convert(String input, Object context) method.","Remove or rename any extra overloads whose signature is (String, Object).","Check that visibility is public and the class is concrete; recompile and inspect the error message, which lists the candidate methods it found."],"exampleFix":"// before\nclass ModeConverter implements Converter<String> {\n  public String convert(String input) { ... }  // wrong arity\n}\n// after\nclass ModeConverter implements Converter<String> {\n  @Override\n  public String convert(String input, Object ignored) { ... }\n}","handlingStrategy":"validation","validationCode":"static void assertSingleConvertMethod(Class<?> converter) {\n  long matches = Arrays.stream(converter.getMethods())\n      .filter(m -> m.getName().equals(\"convert\"))\n      .filter(m -> m.getParameterCount() == 2)\n      .filter(m -> m.getParameterTypes()[0] == String.class\n               && m.getParameterTypes()[1] == Object.class)\n      .count();\n  Preconditions.checkState(matches == 1,\n      \"Converter %s must have exactly one convert(String, Object) method, found %d\",\n      converter.getName(), matches);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always implement com.google.devtools.common.options.Converter and use @Override on convert(String, Object) so signature mistakes fail fast.","Do not add (String, Object) overloads of convert; give helpers different names."],"tags":["java","bazel","annotation-processing","options","compile-time","converter","method-resolution"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}