{"record":{"id":"5de9085ced415c8b","repo":"bazelbuild/bazel","slug":"option-that-allows-multiple-occurrences-must-be-of-5de908","errorCode":null,"errorMessage":"Option that allows multiple occurrences must be of type %s, where E is the type of an individual command-line mention of this option, but is of type %s","messagePattern":"Option that allows multiple occurrences must be of type (.+?), where E is the type of an individual command-line mention of this option, but is of type (.+?)","errorType":"validation","errorClass":"OptionProcessorException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java","lineNumber":594,"sourceCode":"      if (optionType.getKind() != TypeKind.DECLARED) {\n        throw new OptionProcessorException(\n            method,\n            \"Option that allows multiple occurrences must be of type %s, but is of type %s\",\n            listType,\n            optionType);\n      }\n      DeclaredType optionDeclaredType = (DeclaredType) optionType;\n      if (!typeUtils.isAssignable(typeUtils.erasure(optionDeclaredType), listType)) {\n        throw new OptionProcessorException(\n            method,\n            \"Option that allows multiple occurrences must be assignable to type %s, but is of type\"\n                + \" %s\",\n            listType,\n            optionType);\n      }\n      List<? extends TypeMirror> genericParameters = optionDeclaredType.getTypeArguments();\n      if (genericParameters.size() != 1) {\n        throw new OptionProcessorException(\n            method,\n            \"Option that allows multiple occurrences must be of type %s, where E is the type of an\"\n                + \" individual command-line mention of this option, but is of type %s\",\n            listType,\n            optionType);\n      }\n      return ImmutableList.of(genericParameters.get(0), optionType);\n    } else {\n      return ImmutableList.of(optionType);\n    }\n  }\n\n  private void checkForDefaultConverter(\n      ExecutableElement method, List<TypeMirror> acceptedConverterReturnTypes, String defaultValue)\n      throws OptionProcessorException {\n    if (defaultConverters == null) {\n      // Bootstrapping. Do not do this check.\n      return;","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java#L576-L612","documentation":"The third shape check for allowMultiple options in Bazel's options annotation processor: the declared List type must have exactly one type argument. Raw List (zero type arguments) or bizarre multi-arity declarations fail, because the processor needs the single element type E to determine the converter for each command-line mention of the option.","triggerScenarios":"@Option(allowMultiple = true) on a field of raw type List (no generic parameter), or a declared type whose getTypeArguments().size() != 1.","commonSituations":"Legacy or quick-and-dirty code using raw List; suppressing generics warnings; refactoring that accidentally drops the type parameter. Note the element type is then used to look up the converter, so leaving it raw makes converter resolution impossible.","solutions":["Parameterize the List with the per-occurrence value type: List<String>, List<Integer>, etc.","Pick the element type to match an available converter (String, boolean, int, and other built-ins each have default converters).","Recompile to confirm."],"exampleFix":"// before\n@Option(\n  name = \"define\",\n  defaultValue = \"null\",\n  allowMultiple = true\n)\n@SuppressWarnings(\"rawtypes\")\npublic static List defines;\n// after\n@Option(\n  name = \"define\",\n  defaultValue = \"null\",\n  allowMultiple = true\n)\npublic static List<String> defines;","handlingStrategy":"type-guard","validationCode":"static void checkMultipleHasOneTypeArg(boolean allowMultiple,\n                                        List<? extends TypeMirror> typeArgs) {\n  if (allowMultiple) {\n    Preconditions.checkState(typeArgs.size() == 1,\n        \"allowMultiple options must be List<E> with exactly one type argument\");\n  }\n}","typeGuard":"static boolean isParameterizedList(java.lang.reflect.Type type) {\n  return type instanceof ParameterizedType p\n      && p.getRawType() == List.class\n      && p.getActualTypeArguments().length == 1;\n}","tryCatchPattern":null,"preventionTips":["Never use raw List; always parameterize with the per-occurrence value type.","Enable -Xlint:rawtypes so raw List declarations surface as warnings before the processor error."],"tags":["java","bazel","annotation-processing","options","compile-time","allow-multiple","generics","raw-types"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}