{"record":{"id":"ff93113e389c6d36","repo":"bazelbuild/bazel","slug":"option-method-must-be-public","errorCode":null,"errorMessage":"@Option method must be public","messagePattern":"@Option method must be public","errorType":"validation","errorClass":"OptionProcessorException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java","lineNumber":329,"sourceCode":"              \"\"\",\n              option.fieldType,\n              fieldName,\n              option.capitalizedFieldName,\n              option.hasSetterInBase ? \"@Override\" : \"\");\n        }\n\n        out.println(\"}\");\n      }\n    } catch (IOException e) {\n      messager.printMessage(\n          Diagnostic.Kind.ERROR,\n          \"Failed to generate implementation for \" + className + \": \" + e.getMessage());\n    }\n  }\n\n  private void checkMethodOption(ExecutableElement method) throws OptionProcessorException {\n    if (!method.getModifiers().contains(Modifier.PUBLIC)) {\n      throw new OptionProcessorException(method, \"@Option method must be public\");\n    }\n    if (!method.getModifiers().contains(Modifier.ABSTRACT)) {\n      throw new OptionProcessorException(method, \"@Option method must be abstract\");\n    }\n\n    String methodName = method.getSimpleName().toString();\n    if (!methodName.startsWith(\"get\")\n        || methodName.length() < 4\n        || !Character.isUpperCase(methodName.charAt(3))) {\n      throw new OptionProcessorException(\n          method, \"Annotated method name must start with 'get' followed by an uppercase letter\");\n    }\n\n    checkOptionName(method);\n    checkOldCategoriesAreNotUsed(method);\n    checkExpansionOptions(method);\n    checkConverter(method);\n    checkEffectTagRationality(method);","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java#L311-L347","documentation":"OptionsClassProcessor is the annotation processor behind @Option-annotated interfaces. When an @Option-annotated method (the interface-method style introduced for BoM-style option interfaces) lacks the public modifier, processing aborts with this compile-time error pointing at the method. The processor must be able to generate an implementing class that overrides the method, which requires public visibility.","triggerScenarios":"Declaring an @Option method in an interface without public — e.g. a package-private or default-visibility getter — and compiling with the options annotation processor on the classpath.","commonSituations":"Writing a new BoM/options interface by hand; refactoring a class with package-private option fields into interface methods; IDE auto-generating getters with default visibility.","solutions":["Mark the annotated method public","Keep the containing interface public too, since generated implementations live elsewhere","Rebuild; the processor re-runs and should proceed past this check"],"exampleFix":"// before\npublic interface MyOptions {\n  @Option(name = \"foo\", effectTags = {OptionEffectTag.NO_OP})\n  String getFoo();\n}\n// after\npublic interface MyOptions {\n  @Option(name = \"foo\", effectTags = {OptionEffectTag.NO_OP})\n  public String getFoo();\n}","handlingStrategy":"validation","validationCode":"// Reflection-style pre-check in tests for options interfaces\nfor (var m : MyOptions.class.getMethods()) {\n  if (m.isAnnotationPresent(Option.class)\n      && !java.lang.reflect.Modifier.isPublic(m.getModifiers())) {\n    throw new AssertionError(\"@Option method not public: \" + m);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Start new option interfaces from an existing conforming example","Enable annotation processor warnings-as-errors early in development","Code-review rule: @Option methods are public abstract getters"],"tags":["bazel","options","annotation-processor","compile-time","java"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}