bazelbuild/bazel · error · OptionProcessorException
Options that are used on the command line as flags must have
Error message
Options that are used on the command line as flags must have names made from word characters only.
What it means
Flag names are used verbatim on the command line, so (unless the option is tagged OptionMetadataTag.INTERNAL) the processor validates the name against the pattern [\w:-]* — word characters plus, as legacy tolerance, '-' and ':'. Any other character (space, '=', '.', '/', '#', etc.) is rejected with this message, which deliberately overstates the restriction to push toward clean names.
Source
Thrown at src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java:364
checkConverter(method);
checkEffectTagRationality(method);
checkMetadataTagAndCategoryRationality(method);
checkNoDefaultValueForMultipleOption(method);
checkDeprecated(method);
}
private void checkOptionName(ExecutableElement method) throws OptionProcessorException {
Option annotation = method.getAnnotation(Option.class);
String optionName = annotation.name();
if (optionName.isEmpty()) {
throw new OptionProcessorException(method, "Option must have an actual name.");
}
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.View on GitHub (pinned to e6e199d060)
Solutions
- Rewrite the name using only letters, digits, underscore, and (if legacy-needed) '-' or ':'
- If a weird name is genuinely required and never user-facing, add metadataTags = {OptionMetadataTag.INTERNAL}
- Prefer snake_case word characters for new flags since '-' and ':' are legacy allowances
Example fix
// before
@Option(name = "foo.bar", effectTags = {OptionEffectTag.NO_OP})
String getFooBar();
// after
@Option(name = "foo_bar", effectTags = {OptionEffectTag.NO_OP})
String getFooBar(); Defensive patterns
Strategy: validation
Validate before calling
// Validate the option name charset ([\w:-]*) outside the processor
var OK = java.util.regex.Pattern.compile("[\\w:-]*");
for (var m : MyOptions.class.getMethods()) {
Option o = m.getAnnotation(Option.class);
if (o != null && !o.name().isEmpty() && !OK.matcher(o.name()).matches()
&& !java.util.List.of(o.metadataTags()).contains(OptionMetadataTag.INTERNAL)) {
throw new AssertionError("Illegal option name: " + o.name());
}
} Prevention
- Use snake_case word characters for new flag names
- Reserve '-' and ':' spellings for legacy options only
- Tag genuinely internal options with OptionMetadataTag.INTERNAL
When it happens
Trigger: Declaring @Option(name = "foo.bar"), "my flag", "foo=value", or any name with non-[\w:-] characters and not marking it INTERNAL.
Common situations: Wanting dotted or namespaced flag names; pasting names from external tooling with spaces or unicode; forgetting that '=' in a name would make '--name=value' ambiguous.
Related errors
- Annotated method name must start with 'get' followed by an u
- @Option method must be public
- @Option method must be abstract
- Option must have an actual name.
- Option does not list at least one OptionEffectTag. If the op
AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14).
Data as JSON: /api/errors/430c8680e3451656.
Report an issue: GitHub.