bazelbuild/bazel · error · OptionProcessorException

Option has metadata tag %s but does not have category UNDOCU

Error message

Option has metadata tag %s but does not have category UNDOCUMENTED. Please fix.

What it means

Thrown at compile time by Bazel's options annotation processor while validating the relationship between an option's metadataTags and its documentationCategory. Options marked with metadata tag HIDDEN or INTERNAL must use documentationCategory = UNDOCUMENTED, because hidden/internal options are by definition excluded from generated documentation.

Source

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

      if (tags.contains(OptionEffectTag.NO_OP)) {
        throw new OptionProcessorException(
            method,
            "Option includes NO_OP with other effects. This doesn't make much sense. Please "
                + "remove NO_OP or the actual effects from the list, whichever is correct.");
      }
    }
  }

  private void checkMetadataTagAndCategoryRationality(ExecutableElement method)
      throws OptionProcessorException {
    Option annotation = method.getAnnotation(Option.class);
    OptionMetadataTag[] metadataTags = annotation.metadataTags();
    OptionDocumentationCategory category = annotation.documentationCategory();

    for (OptionMetadataTag tag : metadataTags) {
      if (tag == OptionMetadataTag.HIDDEN || tag == OptionMetadataTag.INTERNAL) {
        if (category != OptionDocumentationCategory.UNDOCUMENTED) {
          throw new OptionProcessorException(
              method,
              "Option has metadata tag %s but does not have category UNDOCUMENTED. Please fix.",
              tag);
        }
      }
    }
  }

  private static final ImmutableSet<String> DEPRECATED_CATEGORIES =
      ImmutableSet.of("undocumented", "hidden", "internal");

  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 \""

View on GitHub (pinned to e6e199d060)

Solutions

  1. Set documentationCategory = OptionDocumentationCategory.UNDOCUMENTED on the flagged option (this is the intended fix in essentially all cases).
  2. Alternatively, if the option should stay documented, remove the HIDDEN/INTERNAL metadata tag that forced the mismatch.
  3. Recompile; the check re-runs on every build of the options class.

Example fix

// before
@Option(
  name = "internal_cache_size",
  defaultValue = "1024",
  documentationCategory = OptionDocumentationCategory.PERFORMANCE,
  effectTags = {OptionEffectTag.EAGER},
  metadataTags = {OptionMetadataTag.INTERNAL}
)
// after
@Option(
  name = "internal_cache_size",
  defaultValue = "1024",
  documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
  effectTags = {OptionEffectTag.EAGER},
  metadataTags = {OptionMetadataTag.INTERNAL}
)
Defensive patterns

Strategy: validation

Validate before calling

static void checkCategoryMatchesMetadata(OptionDocumentationCategory category,
                                        Set<OptionMetadataTag> metadataTags) {
  if (metadataTags.contains(HIDDEN) || metadataTags.contains(INTERNAL)) {
    Preconditions.checkState(category == OptionDocumentationCategory.UNDOCUMENTED,
        "HIDDEN/INTERNAL options must use UNDOCUMENTED category");
  }
}

Prevention

When it happens

Trigger: An @Option method with metadataTags containing OptionMetadataTag.HIDDEN or OptionMetadataTag.INTERNAL while documentationCategory is anything other than UNDOCUMENTED, e.g. documentationCategory = OptionDocumentationCategory.LOGGING with metadataTags = {OptionMetadataTag.INTERNAL}.

Common situations: Marking a previously-documented option as HIDDEN or INTERNAL but forgetting to flip its documentationCategory to UNDOCUMENTED; writing a new internal option by copying a documented one and only changing metadataTags; refactoring flags between categories during cleanup.

Related errors


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