{"record":{"id":"59ca933e29c491bd","repo":"bazelbuild/bazel","slug":"option-includes-unknown-with-other-known-effects","errorCode":null,"errorMessage":"Option includes UNKNOWN with other, known, effects. Please remove UNKNOWN from the list.","messagePattern":"Option includes UNKNOWN with other, known, effects\\. Please remove UNKNOWN from the list\\.","errorType":"validation","errorClass":"OptionProcessorException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java","lineNumber":385,"sourceCode":"                + \"characters only.\");\n      }\n    }\n  }\n\n  private void checkEffectTagRationality(ExecutableElement method) throws OptionProcessorException {\n    Option annotation = method.getAnnotation(Option.class);\n    OptionEffectTag[] effectTags = annotation.effectTags();\n    if (effectTags.length < 1) {\n      throw new OptionProcessorException(\n          method,\n          \"Option does not list at least one OptionEffectTag. If the option has no effect, \"\n              + \"please be explicit and add NO_OP. Otherwise, add a tag representing its effect.\");\n    } else if (effectTags.length > 1) {\n      // If there are more than 1 tag, make sure that NO_OP and UNKNOWN is not one of them.\n      // These don't make sense if other effects are listed.\n      ImmutableList<OptionEffectTag> tags = ImmutableList.copyOf(effectTags);\n      if (tags.contains(OptionEffectTag.UNKNOWN)) {\n        throw new OptionProcessorException(\n            method,\n            \"Option includes UNKNOWN with other, known, effects. Please remove UNKNOWN from \"\n                + \"the list.\");\n      }\n      if (tags.contains(OptionEffectTag.NO_OP)) {\n        throw new OptionProcessorException(\n            method,\n            \"Option includes NO_OP with other effects. This doesn't make much sense. Please \"\n                + \"remove NO_OP or the actual effects from the list, whichever is correct.\");\n      }\n    }\n  }\n\n  private void checkMetadataTagAndCategoryRationality(ExecutableElement method)\n      throws OptionProcessorException {\n    Option annotation = method.getAnnotation(Option.class);\n    OptionMetadataTag[] metadataTags = annotation.metadataTags();\n    OptionDocumentationCategory category = annotation.documentationCategory();","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java#L367-L403","documentation":"This error is thrown at compile time by the annotation processor that validates @Option-annotated methods in Bazel options classes. It means the option declares more than one OptionEffectTag in effectTags and one of them is UNKNOWN. UNKNOWN is a placeholder meaning 'the effect has not been categorized yet', so mixing it with concrete effects is contradictory and rejected.","triggerScenarios":"An @Option method whose effectTags attribute contains UNKNOWN together with at least one other tag, e.g. @Option(name = \"foo\", effectTags = {OptionEffectTag.UNKNOWN, OptionEffectTag.EAGER}). The check only fires when effectTags.length > 1.","commonSituations":"Copying an existing option that used UNKNOWN and then adding a real effect tag without removing UNKNOWN; auto-completing OptionEffectTag entries in an IDE and accidentally keeping UNKNOWN; migrating legacy options that were never properly tagged.","solutions":["Open the flagged @Option method and inspect its effectTags array.","Decide which single concrete effect(s) apply (e.g. EAGER, LAZY, LOSES_INCREMENTAL_STATE, CHANGES_INPUTS) and remove OptionEffectTag.UNKNOWN from the list.","If genuinely no effect is known, leave UNKNOWN as the ONLY tag (length 1 does not trigger this error), or use NO_OP alone if the option intentionally does nothing.","Recompile; the processor error disappears once UNKNOWN is not combined with other tags."],"exampleFix":"// before\n@Option(\n  name = \"experimental_foo\",\n  defaultValue = \"false\",\n  documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,\n  effectTags = {OptionEffectTag.UNKNOWN, OptionEffectTag.CHANGES_INPUTS},\n  metadataTags = {OptionMetadataTag.EXPERIMENTAL}\n)\n// after\n@Option(\n  name = \"experimental_foo\",\n  defaultValue = \"false\",\n  documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,\n  effectTags = {OptionEffectTag.CHANGES_INPUTS},\n  metadataTags = {OptionMetadataTag.EXPERIMENTAL}\n)","handlingStrategy":"validation","validationCode":"// Before adding effectTags, assert UNKNOWN appears alone or not at all\nstatic List<OptionEffectTag> sanitizeEffects(List<OptionEffectTag> tags) {\n  if (tags.size() > 1) {\n    Preconditions.checkState(!tags.contains(OptionEffectTag.UNKNOWN),\n        \"UNKNOWN must not be combined with other OptionEffectTags: %s\", tags);\n  }\n  return tags;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never leave UNKNOWN in a copied @Option definition; replace it during the copy.","During option-definition review, check effectTags contains either exactly [UNKNOWN] or only concrete tags.","Treat UNKNOWN as a TODO marker: resolve it before submitting."],"tags":["java","bazel","annotation-processing","options","compile-time","option-effect-tags"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}