bazelbuild/bazel · error · OptionProcessorException

Default values for multiple options are not allowed - use "n

Error message

Default values for multiple options are not allowed - use "null" special value

What it means

Bazel's options annotation processor forbids default values on options with allowMultiple = true. List-valued options start empty by construction; their defaultValue must be the special string "null" (meaning 'no default'). The only exceptions are the two grandfathered options named runs_per_test and flaky_test_attempts.

Source

Thrown at src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java:458

          "Can't set an option to be both an expansion option and have implicit requirements.");
    }

    if (isExpansion || hasImplicitRequirements) {
      if (annotation.allowMultiple()) {
        throw new OptionProcessorException(
            method,
            "Can't set an option to accumulate multiple values and let it expand to other flags.");
      }
    }
  }

  private void checkNoDefaultValueForMultipleOption(ExecutableElement method)
      throws OptionProcessorException {
    Option annotation = method.getAnnotation(Option.class);
    if (annotation.allowMultiple()
        && !annotation.defaultValue().equals("null")
        && !ImmutableList.of("runs_per_test", "flaky_test_attempts").contains(annotation.name())) {
      throw new OptionProcessorException(
          method,
          "Default values for multiple options are not allowed - use \"null\" special value");
    }
  }

  // TODO(Silic0nS0ldier): Remove this allowlist once all tests have been fixed.
  private static final ImmutableList<String> NO_OP_OPTION_ALLOWLIST =
      ImmutableList.of(
          "com.google.devtools.build.lib.analysis.AnalysisCachingTest.",
          "com.google.devtools.build.lib.analysis.config.BuildOptionDetailsTest.",
          "com.google.devtools.build.lib.analysis.config.BuildOptionsTest.",
          "com.google.devtools.build.lib.analysis.LateBoundSplitUtil.",
          "com.google.devtools.build.lib.analysis.producers.BuildConfigurationKeyMapProducerTest.",
          "com.google.devtools.build.lib.analysis.producers.BuildConfigurationKeyProducerTest.",
          "com.google.devtools.build.lib.analysis.RequiredConfigFragmentsTest.",
          "com.google.devtools.build.lib.analysis.starlark.StarlarkTransitionTest.",
          "com.google.devtools.build.lib.analysis.starlark.StarlarkTransitionTest.",
          "com.google.devtools.build.lib.analysis.util.ConfigurationTestCase.",

View on GitHub (pinned to e6e199d060)

Solutions

  1. Set defaultValue = "null" (the literal string) on the allowMultiple option; the list is then initialized empty by the options parser.
  2. If an initial non-empty value is genuinely required, implement it in the options class's converter or in code that consumes the option, not via defaultValue.
  3. Do not rename your option to runs_per_test/flaky_test_attempts to sneak past the allowlist — those names are hardcoded exceptions pending cleanup.
  4. Recompile to confirm.

Example fix

// before
@Option(
  name = "extra_actions",
  defaultValue = "[]",
  allowMultiple = true,
  documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
  effectTags = {OptionEffectTag.EAGER}
)
// after
@Option(
  name = "extra_actions",
  defaultValue = "null",
  allowMultiple = true,
  documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
  effectTags = {OptionEffectTag.EAGER}
)
Defensive patterns

Strategy: validation

Validate before calling

static String checkMultipleDefault(String optionName, boolean allowMultiple, String defaultValue) {
  if (allowMultiple && !"null".equals(defaultValue)
      && !List.of("runs_per_test", "flaky_test_attempts").contains(optionName)) {
    throw new IllegalArgumentException(
        "allowMultiple option '" + optionName + "' must use defaultValue = \"null\"");
  }
  return defaultValue;
}

Prevention

When it happens

Trigger: Declaring @Option(allowMultiple = true, defaultValue = "something") where the option name is not exactly "runs_per_test" or "flaky_test_attempts". Any defaultValue string other than "null" triggers it.

Common situations: Writing a new repeatable flag and habitually filling in a default; migrating an old option to allowMultiple while keeping its previous default; misunderstanding that "null" is a sentinel literal, not a Java null reference.

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/e57c443ff05a5e33. Report an issue: GitHub.