bazelbuild/bazel · error · OptionProcessorException
Options annotated with @Deprecated must have metadata tag DE
Error message
Options annotated with @Deprecated must have metadata tag DEPRECATED.
What it means
The mirror of the previous check in Bazel's options annotation processor: an @Option method annotated with java.lang.@Deprecated must also declare OptionMetadataTag.DEPRECATED in metadataTags, so that Bazel's generated documentation marks the flag as deprecated consistently with the Java API.
Source
Thrown at src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java:531
// Allowlist for tests - these are in the process of being fixed.
String enclosingClassName = method.getEnclosingElement().toString();
boolean allowlisted =
NO_OP_OPTION_ALLOWLIST.stream().anyMatch(enclosingClassName::startsWith);
if (!allowlisted) {
throw new OptionProcessorException(
method,
"No-op options must be annotated with @Deprecated, or have metadata tag HIDDEN or"
+ " INTERNAL. Alternatively add %s to the allowlist.",
enclosingClassName);
}
}
if (hasDeprecatedMetadataTag && !hasDeprecatedAnnotation) {
throw new OptionProcessorException(
method, "Options with metadata tag DEPRECATED must be annotated with @Deprecated.");
}
if (hasDeprecatedAnnotation && !hasDeprecatedMetadataTag) {
throw new OptionProcessorException(
method, "Options annotated with @Deprecated must have metadata tag DEPRECATED.");
}
}
private void checkConverter(ExecutableElement method) throws OptionProcessorException {
TypeMirror optionType = method.getReturnType();
Option annotation = method.getAnnotation(Option.class);
ImmutableList<TypeMirror> acceptedConverterReturnTypes =
getAcceptedConverterReturnTypes(method);
// For simple, static expansions, don't accept non-Void types.
if (annotation.expansion().length != 0
&& !typeUtils.isSameType(
optionType, elementUtils.getTypeElement(Void.class.getCanonicalName()).asType())) {
throw new OptionProcessorException(
method,
"Option is an expansion flag with a static expansion, but does not have Void type.");
}View on GitHub (pinned to e6e199d060)
Solutions
- Add OptionMetadataTag.DEPRECATED to the method's metadataTags array.
- If the deprecation itself was accidental, remove @Deprecated from the method instead.
- Recompile to confirm.
Example fix
// before
@Deprecated
@Option(
name = "legacy_path",
defaultValue = "null",
effectTags = {OptionEffectTag.EAGER}
)
// after
@Deprecated
@Option(
name = "legacy_path",
defaultValue = "null",
effectTags = {OptionEffectTag.EAGER},
metadataTags = {OptionMetadataTag.DEPRECATED}
) Defensive patterns
Strategy: validation
Validate before calling
static void checkAnnotationMatchesDeprecatedTag(boolean hasDeprecatedAnnotation,
boolean hasDeprecatedTag) {
Preconditions.checkState(!hasDeprecatedAnnotation || hasDeprecatedTag,
"@Deprecated options must add metadataTags DEPRECATED");
} Prevention
- Never apply a bare @Deprecated to an @Option method; always include the DEPRECATED metadata tag.
- When deprecating whole options classes, check each @Option method individually.
When it happens
Trigger: A method carrying both @Option and @Deprecated whose metadataTags attribute does not include OptionMetadataTag.DEPRECATED.
Common situations: Applying @Deprecated to an options class or method during ordinary Java cleanup without updating the @Option metadata; deprecating an option for removal but wanting it to stay documented (the tag, not category, is how deprecation is expressed now).
Related errors
- Options with metadata tag DEPRECATED must be annotated with
- Option includes NO_OP with other effects. This doesn't make
- Option has metadata tag %s but does not have category UNDOCU
- No-op options must be annotated with @Deprecated, or have me
- Option includes UNKNOWN with other, known, effects. Please r
AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14).
Data as JSON: /api/errors/a740cb7b333dedd0.
Report an issue: GitHub.