{"record":{"id":"088efdb05301f26b","repo":"bazelbuild/bazel","slug":"options-with-metadata-tag-deprecated-must-be-annot","errorCode":null,"errorMessage":"Options with metadata tag DEPRECATED must be annotated with @Deprecated.","messagePattern":"Options with metadata tag DEPRECATED must be annotated with @Deprecated\\.","errorType":"validation","errorClass":"OptionProcessorException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java","lineNumber":527,"sourceCode":"    if (effectTags.contains(OptionEffectTag.NO_OP)\n        && !metadataTags.contains(OptionMetadataTag.HIDDEN)\n        && !metadataTags.contains(OptionMetadataTag.INTERNAL)\n        && !hasDeprecatedAnnotation) {\n      // Allowlist for tests - these are in the process of being fixed.\n      String enclosingClassName = method.getEnclosingElement().toString();\n      boolean allowlisted =\n          NO_OP_OPTION_ALLOWLIST.stream().anyMatch(enclosingClassName::startsWith);\n      if (!allowlisted) {\n        throw new OptionProcessorException(\n            method,\n            \"No-op options must be annotated with @Deprecated, or have metadata tag HIDDEN or\"\n                + \" INTERNAL. Alternatively add %s to the allowlist.\",\n            enclosingClassName);\n      }\n    }\n\n    if (hasDeprecatedMetadataTag && !hasDeprecatedAnnotation) {\n      throw new OptionProcessorException(\n          method, \"Options with metadata tag DEPRECATED must be annotated with @Deprecated.\");\n    }\n    if (hasDeprecatedAnnotation && !hasDeprecatedMetadataTag) {\n      throw new OptionProcessorException(\n          method, \"Options annotated with @Deprecated must have metadata tag DEPRECATED.\");\n    }\n  }\n\n  private void checkConverter(ExecutableElement method) throws OptionProcessorException {\n    TypeMirror optionType = method.getReturnType();\n    Option annotation = method.getAnnotation(Option.class);\n    ImmutableList<TypeMirror> acceptedConverterReturnTypes =\n        getAcceptedConverterReturnTypes(method);\n\n    // For simple, static expansions, don't accept non-Void types.\n    if (annotation.expansion().length != 0\n        && !typeUtils.isSameType(\n            optionType, elementUtils.getTypeElement(Void.class.getCanonicalName()).asType())) {","sourceCodeStart":509,"sourceCodeEnd":545,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java#L509-L545","documentation":"Bazel's options annotation processor keeps the DEPRECATED metadata tag and the Java @Deprecated annotation in lockstep. This error fires when an @Option method declares OptionMetadataTag.DEPRECATED in metadataTags but is not annotated with java.lang.@Deprecated.","triggerScenarios":"@Option(..., metadataTags = {OptionMetadataTag.DEPRECATED}) on a method without @Deprecated.","commonSituations":"Marking a flag deprecated in Bazel's generated documentation but forgetting the language-level annotation; copying an option definition that includes the tag; tooling or templates that add metadataTags automatically.","solutions":["Add @Deprecated directly to the flagged @Option method (its paired check will then also pass).","If the option is not actually deprecated, remove OptionMetadataTag.DEPRECATED from metadataTags instead.","Recompile to confirm."],"exampleFix":"// before\n@Option(\n  name = \"old_way\",\n  defaultValue = \"true\",\n  effectTags = {OptionEffectTag.NO_OP},\n  metadataTags = {OptionMetadataTag.DEPRECATED}\n)\n// after\n@Deprecated\n@Option(\n  name = \"old_way\",\n  defaultValue = \"true\",\n  effectTags = {OptionEffectTag.NO_OP},\n  metadataTags = {OptionMetadataTag.DEPRECATED}\n)","handlingStrategy":"validation","validationCode":"static void checkDeprecatedTagMatchesAnnotation(boolean hasDeprecatedTag,\n                                                 boolean hasDeprecatedAnnotation) {\n  Preconditions.checkState(!hasDeprecatedTag || hasDeprecatedAnnotation,\n      \"metadataTags DEPRECATED requires the @Deprecated annotation\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add @Deprecated and OptionMetadataTag.DEPRECATED as one atomic edit.","Use a code template or IDE live template for deprecating options so both markers are always applied."],"tags":["java","bazel","annotation-processing","options","compile-time","deprecation","option-metadata-tags"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}