bazelbuild/bazel · error · OptionProcessorException

Documentation level is no longer read from the option catego

Error message

Documentation level is no longer read from the option category. Category "%s" is disallowed, see OptionMetadataTags for the relevant tags.

What it means

This compile-time error is produced by Bazel's options annotation processor. The old API encoded documentation level (undocumented/hidden/internal) as free-form strings in the option's category attribute; that mechanism was replaced by OptionMetadataTag (HIDDEN, INTERNAL, etc.) and OptionDocumentationCategory. The processor maintains an allowlist-free blocklist of the legacy category strings and rejects any option still using one.

Source

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

      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 \""
              + 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.");
    }

View on GitHub (pinned to e6e199d060)

Solutions

  1. Remove the category = "..." parameter from the @Option annotation.
  2. Express documentation level via metadataTags: use OptionMetadataTag.HIDDEN or OptionMetadataTag.INTERNAL instead of the old category strings.
  3. Set documentationCategory = OptionDocumentationCategory.UNDOCUMENTED for hidden/internal options (required by the related metadata check).
  4. For all other options, choose an accurate OptionDocumentationCategory value describing where the flag belongs in generated docs.

Example fix

// before
@Option(
  name = "legacy_hidden_flag",
  defaultValue = "true",
  category = "hidden",
  effectTags = {OptionEffectTag.NO_OP}
)
// after
@Option(
  name = "legacy_hidden_flag",
  defaultValue = "true",
  documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
  effectTags = {OptionEffectTag.NO_OP},
  metadataTags = {OptionMetadataTag.HIDDEN}
)
Defensive patterns

Strategy: validation

Validate before calling

// Reject legacy category strings before writing options code
private static final Set<String> LEGACY = Set.of("undocumented", "hidden", "internal");

static String assertModernCategory(String category) {
  Preconditions.checkArgument(!LEGACY.contains(category),
      "Legacy category '%s' removed; use OptionMetadataTag instead", category);
  return category;
}

Prevention

When it happens

Trigger: An @Option method whose category() attribute (or the @Option annotation's category parameter) is exactly "undocumented", "hidden", or "internal" — the strings in DEPRECATED_CATEGORIES.

Common situations: Upgrading Bazel or the options library to a version where the category-based scheme was removed; porting old options classes written against the pre-migration API; merging legacy code that predates OptionMetadataTag.

Related errors


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