pytorch/pytorch · error · ValueError

Brackets are not balanced

Error message

Brackets are not balanced

What it means

Thrown by the character loop in `ParsedExpression.__init__` (functorch/einops `_parsing.py`). A closing `)` is encountered while no bracket group is open (`bracket_group is None`), i.e. an unmatched close parenthesis.

Source

Thrown at functorch/einops/_parsing.py:146

                    self.composition.append([axis_name])
                else:
                    bracket_group.append(axis_name)

        current_identifier = None
        for char in expression:
            if char in "() ":
                if current_identifier is not None:
                    add_axis_name(current_identifier)
                current_identifier = None
                if char == "(":
                    if bracket_group is not None:
                        raise ValueError(
                            "Axis composition is one-level (brackets inside brackets not allowed)"
                        )
                    bracket_group = []
                elif char == ")":
                    if bracket_group is None:
                        raise ValueError("Brackets are not balanced")
                    self.composition.append(bracket_group)
                    bracket_group = None
            elif str.isalnum(char) or char in ["_", _ellipsis]:
                if current_identifier is None:
                    current_identifier = char
                else:
                    current_identifier += char
            else:
                raise ValueError(f"Unknown character '{char}'")

        if bracket_group is not None:
            raise ValueError(f"Imbalanced parentheses in expression: '{expression}'")
        if current_identifier is not None:
            add_axis_name(current_identifier)

    @staticmethod
    def check_axis_name_return_reason(
        name: str, allow_underscore: bool = False

View on GitHub (pinned to dcd2ecae77)

Solutions

  1. Balance the parentheses in that side of the pattern
  2. Lint the pattern string before use: `expr.count('(') == expr.count(')')`
  3. Simplify the pattern into multiple chained rearrange calls if it is getting hard to read

Example fix

# before
y = rearrange(x, 'h w) -> (h w)')

# after
y = rearrange(x, 'h w -> (h w)')
Defensive patterns

Strategy: validation

Validate before calling

def balanced_parens(expr: str) -> bool:
    depth = 0
    for ch in expr:
        if ch == "(":
            depth += 1
        elif ch == ")":
            depth -= 1
            if depth < 0:
                return False
    return depth == 0

Try / catch

try:
    y = rearrange(x, pattern)
except ValueError as e:
    if "not balanced" in str(e):
        raise ValueError(f"unbalanced ')' in {pattern!r}") from e
    raise

Prevention

When it happens

Trigger: Patterns like `'a) b -> a b'`, `'(h w)) -> h w'`, or a stray `)` pasted into the pattern.

Common situations: Typos; unbalanced parentheses when patterns are built by f-string concatenation; editing a pattern and deleting an opening `(`.

Related errors


AI-assisted analysis of pytorch/pytorch@dcd2ecae77 (2026-08-14). Data as JSON: /api/errors/24d74f250b0f0949. Report an issue: GitHub.