jax-ml/jax · error · ValueError

Brackets are not balanced

Error message

Brackets are not balanced

What it means

A closing ')' was encountered while current_compound_dim is None, i.e. no compound factor is open. Parentheses in the rule must be balanced per operand/result expression.

Source

Thrown at jax/_src/custom_partitioning_sharding_rule.py:288

        batching_group = str(int(batching_group_str))
      else:
        batching_group = "0"

      add_factor(f"{BATCHING}{batching_group}")
      continue
    if char in "(), ":
      if current_factor is not None:
        add_factor(current_factor)
        current_factor = None
      if char == "(":
        if current_compound_dim is not None:
          raise ValueError(
              "Compound factors should be one level, nested brackets are not"
              " allowed")
        current_compound_dim = []
      elif char == ")":
        if current_compound_dim is None:
          raise ValueError("Brackets are not balanced")
        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:

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Add the missing opening '(' so each ')' pairs with a '('
  2. Re-count parentheses in each comma-separated operand/result expression

Example fix

# before
rule = 'i)->(i'
# after
rule = '(i)->(i)'
Defensive patterns

Strategy: validation

Validate before calling

import re
for side in rule.split('->'):
    depth = 0
    for c in side:
        depth += c == '('
        depth -= c == ')'
        assert depth >= 0, 'unbalanced ) '
    assert depth == 0, 'unbalanced ('

Type guard

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

Prevention

When it happens

Trigger: Rule fragment like 'i),j' or 'ij)->(ji' with a stray closing parenthesis.

Common situations: Hand-editing rule strings and deleting an opening '(' but not the ')'.

Related errors


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