bazelbuild/bazel · error · OptionProcessorException

Annotated method name must start with 'get' followed by an…

Error message

Annotated method name must start with 'get' followed by an uppercase letter

What it means

The options annotation processor enforces a naming convention on @Option interface methods: the name must start with 'get', be at least 4 characters, and the 4th character (index 3) must be uppercase — the standard Java bean getter shape. This keeps the generated implementation and documentation consistent with the flag's accessors.

Solutions

  1. Rename the method to getFoo / getFooBar form (get + flag name in CamelCase)
  2. For booleans keep the get prefix too (getFoo, not isFoo) — the flag still uses --nofoo negation at the CLI level
  3. Update call sites or add a delegating accessor elsewhere if you need a different public name

Example fix

// before
@Option(name = "foo", effectTags = {OptionEffectTag.NO_OP})
String foo();
// after
@Option(name = "foo", effectTags = {OptionEffectTag.NO_OP})
String getFoo();
Defensive patterns

Strategy: validation

Validate before calling

// Enforce the get+Uppercase convention in a build-time check
var NAME = java.util.regex.Pattern.compile("get[A-Z].*");
for (var m : MyOptions.class.getMethods()) {
  if (m.isAnnotationPresent(Option.class) && !NAME.matcher(m.getName()).matches()) {
    throw new AssertionError("@Option method name must be getFoo-style: " + m.getName());
  }
}

Prevention

When it happens

Trigger: Annotating methods like foo(), getfoo(), get(), or getFoo vs isFoo-style names — anything not matching get + Uppercase — with @Option in an options interface.

Common situations: Naming a getter after the flag without the get prefix (e.g. experimentalCxxFlags()); 'is' prefix for booleans (isFoo) which the convention rejects; abbreviation casing like getURL that starts lowercase after 'get'.

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/473a3c185190a092. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java:339

      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);
    checkMetadataTagAndCategoryRationality(method);
    checkNoDefaultValueForMultipleOption(method);
    checkDeprecated(method);
  }

  private void checkOptionName(ExecutableElement method) throws OptionProcessorException {
    Option annotation = method.getAnnotation(Option.class);
    String optionName = annotation.name();
    if (optionName.isEmpty()) {
      throw new OptionProcessorException(method, "Option must have an actual name.");

View on GitHub (pinned to e6e199d060)