bazelbuild/bazel · error · OptionProcessorException
Option does not list at least one OptionEffectTag. If the op
Error message
Option does not list at least one OptionEffectTag. If the option has no effect, please be explicit and add NO_OP. Otherwise, add a tag representing its effect.
What it means
Every @Option must declare at least one OptionEffectTag in its annotation — the machine-readable description of what setting the flag affects, used for option filtering and documentation. Zero tags fails this check; the message tells you to either declare a real effect or explicitly mark NO_OP when the flag truly has no effect.
Source
Thrown at src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java:376
}
if (!ImmutableList.copyOf(annotation.metadataTags()).contains(OptionMetadataTag.INTERNAL)) {
if (!Pattern.matches("([\\w:-])*", optionName)) {
// Ideally, this would be just \w, but - and : are needed for legacy options. We can lie in
// the error though, no harm in encouraging good behavior.
throw new OptionProcessorException(
method,
"Options that are used on the command line as flags must have names made from word "
+ "characters only.");
}
}
}
private void checkEffectTagRationality(ExecutableElement method) throws OptionProcessorException {
Option annotation = method.getAnnotation(Option.class);
OptionEffectTag[] effectTags = annotation.effectTags();
if (effectTags.length < 1) {
throw new OptionProcessorException(
method,
"Option does not list at least one OptionEffectTag. If the option has no effect, "
+ "please be explicit and add NO_OP. Otherwise, add a tag representing its effect.");
} else if (effectTags.length > 1) {
// If there are more than 1 tag, make sure that NO_OP and UNKNOWN is not one of them.
// These don't make sense if other effects are listed.
ImmutableList<OptionEffectTag> tags = ImmutableList.copyOf(effectTags);
if (tags.contains(OptionEffectTag.UNKNOWN)) {
throw new OptionProcessorException(
method,
"Option includes UNKNOWN with other, known, effects. Please remove UNKNOWN from "
+ "the list.");
}
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.");View on GitHub (pinned to e6e199d060)
Solutions
- Pick accurate tags from OptionEffectTag (e.g. EAGERNESS_FOR_OUTPUT, EXECUTION_STRATEGY, LOADING_AND_ANALYSIS, UNKNOWN) matching the flag's real effect
- If the flag genuinely does nothing (deprecated placeholder, marker), declare effectTags = {OptionEffectTag.NO_OP}
- Note the sibling rule: NO_OP and UNKNOWN cannot be combined with other tags
Example fix
// before
@Option(name = "foo", defaultValue = "x")
String getFoo();
// after
@Option(name = "foo", defaultValue = "x", effectTags = {OptionEffectTag.NO_OP})
String getFoo(); Defensive patterns
Strategy: validation
Validate before calling
// Ensure every @Option declares at least one effect tag
for (var m : MyOptions.class.getMethods()) {
Option o = m.getAnnotation(Option.class);
if (o != null && o.effectTags().length == 0) {
throw new AssertionError("@Option " + o.name() + " needs at least one OptionEffectTag");
}
} Prevention
- Choose the effect tag as part of designing the flag, not as an afterthought
- Use NO_OP only for flags with no effect and never alongside other tags
- Copy a fully-annotated existing @Option when adding new flags
When it happens
Trigger: Writing @Option(name = "x", defaultValue = "y") with no effectTags array; adding a new flag quickly and skipping annotation metadata.
Common situations: New flag development; copying an old pre-annotation-mandate declaration; refactoring options where effectTags were dropped during merges.
Related errors
- @Option method must be public
- @Option method must be abstract
- Annotated method name must start with 'get' followed by an u
- Option must have an actual name.
- Options that are used on the command line as flags must have
AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14).
Data as JSON: /api/errors/ef552d62204484fb.
Report an issue: GitHub.