bazelbuild/bazel · error · OptionProcessorException

Can't set an option to be both an expansion option and have

Error message

Can't set an option to be both an expansion option and have implicit requirements.

What it means

Bazel's options annotation processor rejects @Option methods that are simultaneously expansion options (non-empty expansion attribute) and carry implicit requirements (non-empty implicitRequirements attribute). Both mechanisms rewrite the command line into other flags, and combining them creates ambiguous expansion semantics, so the processor forbids it at compile time.

Source

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

  private void checkOldCategoriesAreNotUsed(ExecutableElement method)
      throws OptionProcessorException {
    Option annotation = method.getAnnotation(Option.class);
    if (DEPRECATED_CATEGORIES.contains(annotation.category())) {
      throw new OptionProcessorException(
          method,
          "Documentation level is no longer read from the option category. Category \""
              + annotation.category()
              + "\" is disallowed, see OptionMetadataTags for the relevant tags.");
    }
  }

  private void checkExpansionOptions(ExecutableElement method) throws OptionProcessorException {
    Option annotation = method.getAnnotation(Option.class);
    boolean isExpansion = annotation.expansion().length > 0;
    boolean hasImplicitRequirements = annotation.implicitRequirements().length > 0;

    if (isExpansion && hasImplicitRequirements) {
      throw new OptionProcessorException(
          method,
          "Can't set an option to be both an expansion option and have implicit requirements.");
    }

    if (isExpansion || hasImplicitRequirements) {
      if (annotation.allowMultiple()) {
        throw new OptionProcessorException(
            method,
            "Can't set an option to accumulate multiple values and let it expand to other flags.");
      }
    }
  }

  private void checkNoDefaultValueForMultipleOption(ExecutableElement method)
      throws OptionProcessorException {
    Option annotation = method.getAnnotation(Option.class);
    if (annotation.allowMultiple()
        && !annotation.defaultValue().equals("null")

View on GitHub (pinned to e6e199d060)

Solutions

  1. Pick one mechanism: if the option should expand statically to other flags, keep expansion and delete implicitRequirements.
  2. If the option needs conditional/required companion flags, keep implicitRequirements and move the flags out of expansion (possibly into the implicit requirements list).
  3. If both sets of flags are truly needed, model them as two separate options, or fold all target flags into implicitRequirements.
  4. Recompile and confirm the processor accepts the option.

Example fix

// before
@Option(
  name = "dual_mode",
  defaultValue = "null",
  documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
  effectTags = {OptionEffectTag.EAGER},
  expansion = {"--foo=1"},
  implicitRequirements = {"--bar=2"}
)
// after (all companion flags as implicit requirements)
@Option(
  name = "dual_mode",
  defaultValue = "null",
  documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
  effectTags = {OptionEffectTag.EAGER},
  implicitRequirements = {"--foo=1", "--bar=2"}
)
Defensive patterns

Strategy: validation

Validate before calling

static void checkNotBothExpansionAndImplicit(String[] expansion,
                                              String[] implicitRequirements) {
  Preconditions.checkState(expansion.length == 0 || implicitRequirements.length == 0,
      "An option cannot be both an expansion and have implicit requirements");
}

Prevention

When it happens

Trigger: Declaring @Option(..., expansion = {"--foo=1"}, implicitRequirements = {"--bar=2"}) — both arrays non-empty on the same option.

Common situations: Extending an existing expansion flag with implicit requirements (or vice versa) instead of choosing one mechanism; merging two option definitions during refactoring; misunderstanding that implicitRequirements is not a complement to expansion.

Related errors


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