jax-ml/jax · error · ValueError

Brackets are not balanced in rule: '{rule}'

Error message

Brackets are not balanced in rule: '{rule}'

What it means

After parsing an entire operand/result side, an open compound factor (current_compound_dim is not None) was never closed. The parser requires all '(' to be matched before the end of the expression.

Source

Thrown at jax/_src/custom_partitioning_sharding_rule.py:307

        if len(current_compound_dim) <= 1:
          raise ValueError("Brackets should contain at least two factors")
        value.append(CompoundFactor(*current_compound_dim))
        current_compound_dim = None
      elif char == ",":
        all_values.append(ArrayMapping(*value))
        value = []
    elif char == "_" or char.isdigit() or char.isalpha():
      if current_factor is None:
        if str.isdigit(char):
          raise ValueError(f"Factor names have to start with a letter, but got '{char}'")
        current_factor = char
      else:
        current_factor += char
    else:
      raise ValueError(f"Unknown character '{char}'")

  if current_compound_dim is not None:
    raise ValueError(f"Brackets are not balanced in rule: '{rule}'")
  if current_factor is not None:
    add_factor(current_factor)
  all_values.append(ArrayMapping(*value))

  return tuple(all_values)

def str_to_sdy_sharding_rule(rule: str, *,
                             reduction_factors: tuple[str, ...] = (),
                             need_replication_factors: tuple[str, ...] = (),
                             permutation_factors: tuple[str, ...] = (),
                             **factor_sizes: int) -> SdyShardingRule:
  """Constructs a SdyShardingRule object from the Einsum notation like string.

  This is done by verifying that the input Einsum notation like string and
  with optional special factors and factor sizes represents a valid sharding
  rule and converting it to an internal representation.

  Args:

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Add the missing ')' for every open '('
  2. If generating rules in code, assert rule.count('(') == rule.count(')') before use

Example fix

# before
rule = '(a,b->(a,b)'
# after
rule = '(a,b)->(a,b)'
Defensive patterns

Strategy: validation

Validate before calling

assert rule.count('(') == rule.count(')'), 'unbalanced parentheses in rule'

Type guard

def parens_balanced(rule: str) -> bool:
    d = 0
    for c in rule:
        d += (c == '(') - (c == ')')
        if d < 0: return False
    return d == 0

Prevention

When it happens

Trigger: Rule like '(a,b->(a,b)' where the first compound factor's ')' is missing.

Common situations: Typos from hand-writing long multi-operand rules.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/9572a57ee029a5b8. Report an issue: GitHub.