bazelbuild/bazel · error · OptionProcessorException
@Option method must be public
Error message
@Option method must be public
What it means
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.
Source
Thrown at src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java:329
""",
option.fieldType,
fieldName,
option.capitalizedFieldName,
option.hasSetterInBase ? "@Override" : "");
}
out.println("}");
}
} catch (IOException e) {
messager.printMessage(
Diagnostic.Kind.ERROR,
"Failed to generate implementation for " + className + ": " + e.getMessage());
}
}
private void checkMethodOption(ExecutableElement method) throws OptionProcessorException {
if (!method.getModifiers().contains(Modifier.PUBLIC)) {
throw new OptionProcessorException(method, "@Option method must be public");
}
if (!method.getModifiers().contains(Modifier.ABSTRACT)) {
throw new OptionProcessorException(method, "@Option method must be abstract");
}
String methodName = method.getSimpleName().toString();
if (!methodName.startsWith("get")
|| methodName.length() < 4
|| !Character.isUpperCase(methodName.charAt(3))) {
throw new OptionProcessorException(
method, "Annotated method name must start with 'get' followed by an uppercase letter");
}
checkOptionName(method);
checkOldCategoriesAreNotUsed(method);
checkExpansionOptions(method);
checkConverter(method);
checkEffectTagRationality(method);View on GitHub (pinned to e6e199d060)
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
Example fix
// before
public interface MyOptions {
@Option(name = "foo", effectTags = {OptionEffectTag.NO_OP})
String getFoo();
}
// after
public interface MyOptions {
@Option(name = "foo", effectTags = {OptionEffectTag.NO_OP})
public String getFoo();
} Defensive patterns
Strategy: validation
Validate before calling
// Reflection-style pre-check in tests for options interfaces
for (var m : MyOptions.class.getMethods()) {
if (m.isAnnotationPresent(Option.class)
&& !java.lang.reflect.Modifier.isPublic(m.getModifiers())) {
throw new AssertionError("@Option method not public: " + m);
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- @Option method must be abstract
- Annotated method name must start with 'get' followed by an u
- Option must have an actual name.
- Options that are used on the command line as flags must have
- Option does not list at least one OptionEffectTag. If the op
AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14).
Data as JSON: /api/errors/ff93113e389c6d36.
Report an issue: GitHub.