ScrapeGraphAI/Scrapegraph-ai · error · ValueError

Missing or unbalanced parentheses in expression.

Error message

Missing or unbalanced parentheses in expression.

What it means

ValueError from parse_expression: the number of '(' does not equal the number of ')' in the expression. Unbalanced parentheses make the grouping undecidable.

Source

Thrown at scrapegraphai/utils/parse_state_keys.py:73

        or "||" in expression
        or "&|" in expression
        or "|&" in expression
    ):
        raise ValueError("Invalid operator usage.")

    open_parentheses = close_parentheses = 0
    for i, char in enumerate(expression):
        if char == "(":
            open_parentheses += 1
        elif char == ")":
            close_parentheses += 1
        if char in "&|" and i + 1 < len(expression) and expression[i + 1] in "&|":
            raise ValueError(
                "Invalid operator placement: operators cannot be adjacent."
            )

    if open_parentheses != close_parentheses:
        raise ValueError("Missing or unbalanced parentheses in expression.")

    def evaluate_simple_expression(exp):
        for or_segment in exp.split("|"):
            and_segment = or_segment.split("&")
            if all(elem.strip() in state for elem in and_segment):
                return [elem.strip() for elem in and_segment if elem.strip() in state]
        return []

    def evaluate_expression(expression):
        while "(" in expression:
            start = expression.rfind("(")
            end = expression.find(")", start)
            sub_exp = expression[start + 1 : end]
            sub_result = evaluate_simple_expression(sub_exp)
            expression = (
                expression[:start] + "|".join(sub_result) + expression[end + 1 :]
            )
        return evaluate_simple_expression(expression)

View on GitHub (pinned to 532dfffbf6)

Solutions

  1. Balance the parentheses: '(a | b) & c'
  2. Lint edge-condition expressions in tests before deploying graph configs

Example fix

# before
expr = '(a & (b | c)'
# after
expr = '(a & (b | c))'
Defensive patterns

Strategy: validation

Validate before calling

assert expression.count("(") == expression.count(")"), "unbalanced parentheses"

Type guard

def has_balanced_parens(expr) -> bool:
    return expr.count("(") == expr.count(")")

Try / catch

try:
    keys = parse_expression(expr, state)
except ValueError as e:
    if expr.count("(") != expr.count(")"):
        expr += ")" * (expr.count("(") - expr.count(")"))
        keys = parse_expression(expr, state)
    else:
        raise

Prevention

When it happens

Trigger: Expressions like '(a & b' or 'a | b))' passed to parse_expression.

Common situations: Dynamically composed conditions where a closing paren is dropped, or hand-written config strings with a typo.

Related errors


AI-assisted analysis of ScrapeGraphAI/Scrapegraph-ai@532dfffbf6 (2026-08-28). Data as JSON: /api/errors/616d66f61825c7a2. Report an issue: GitHub.