bazelbuild/bazel · error · OptionsParsingException
Tried to expand option too many times
Error message
Tried to expand option too many times
What it means
OptionPriority.getChildPriority refuses to compute a child priority for an OptionPriority that has already been expanded once. Expansion of an option into child options may only happen one level deep per priority node; the alreadyExpanded flag is set on the first expansion and any second call fails fast instead of producing unbounded or ambiguous ordering.
Source
Thrown at src/main/java/com/google/devtools/common/options/OptionPriority.java:77
return new OptionPriority(
priority.priorityCategory,
ImmutableList.<Integer>builder()
.addAll(priority.priorityIndices.subList(0, lastElementPosition))
.add(priority.priorityIndices.get(lastElementPosition) + 1)
.build());
}
/**
* Some options are expanded to other options, and the children options need to have their order
* preserved while maintaining their position between the options that flank the parent option.
*
* @return the priority for the first child of the passed priority. This child's ordering can be
* tracked the same way that the parent's was.
*/
public static OptionPriority getChildPriority(OptionPriority parentPriority)
throws OptionsParsingException {
if (parentPriority.alreadyExpanded) {
throw new OptionsParsingException("Tried to expand option too many times");
}
// Prevent this option from being re-expanded.
parentPriority.alreadyExpanded = true;
// The child priority has 1 more level of nesting than its parent.
return new OptionPriority(
parentPriority.priorityCategory,
ImmutableList.<Integer>builder().addAll(parentPriority.priorityIndices).add(0).build());
}
public PriorityCategory getPriorityCategory() {
return priorityCategory;
}
@Override
public int compareTo(OptionPriority o) {
if (priorityCategory.equals(o.priorityCategory)) {
for (int i = 0; i < priorityIndices.size() && i < o.priorityIndices.size(); ++i) {View on GitHub (pinned to e6e199d060)
Solutions
- Flatten the expansion: make the parent option expand directly to the final leaf flags instead of expanding to another expansion option
- If you drive expansion programmatically, create a fresh priority context for each expansion round instead of reusing the parent's OptionPriority
- Audit custom OptionDefinition expansion lists for chained expansion options and remove the intermediate option
Example fix
// before
@Option(name = "aspect", expansion = {"experimental_nested"})
// after — expand directly to leaves
@Option(name = "aspect", expansion = {"--experimental_leaf_a", "--experimental_leaf_b"}) Defensive patterns
Strategy: validation
Validate before calling
// Before programmatic expansion, ensure the priority node is fresh
if (expandedPriorities.contains(parentPriority)) {
throw new IllegalStateException("Refusing to re-expand priority; flatten expansion instead");
}
OptionsParserImplResult r = impl.parseArgsAsExpansionOfOption(option, source, args); Try / catch
Wrap parseArgsAsExpansionOfOption in try/catch for OptionsParsingException and surface 'chained expansion' as the likely cause when the message is 'Tried to expand option too many times'.
Prevention
- Never define an expansion option that expands to another expansion option
- Keep expansion lists flat — leaf flags only
- When driving multiple expansion rounds, track which OptionPriority objects were already used
When it happens
Trigger: Calling OptionsParser.parseArgsAsExpansionOfOption (or OptionPriority.getChildPriority) twice for options that share the same OptionPriority instance — typically an option whose expansion itself contains an expandable option, i.e. nested/chained expansions through the same priority object.
Common situations: Defining an @Option(expansion = {...}) whose expansion list contains another expansion option; library code that re-expands the same args in a second parsing round using the stored priority.
Related errors
- Malformed value of --invocation_policy:
- Unrecognized arguments:
- Invalid options syntax: %s Note: Negative target patterns ca
- Invalid options syntax: %s
- Illegal use of 'no' prefix on non-boolean option: %s
AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14).
Data as JSON: /api/errors/d827da5df11510fe.
Report an issue: GitHub.