{"record":{"id":"df339f39b10ab1a9","repo":"ScrapeGraphAI/Scrapegraph-ai","slug":"missing-or-unbalanced-parentheses-in-expression","errorCode":null,"errorMessage":"Missing or unbalanced parentheses in expression.","messagePattern":"Missing or unbalanced parentheses in expression\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scrapegraphai/nodes/base_node.py","lineNumber":193,"sourceCode":"            or \"&|\" in expression\n            or \"|&\" in expression\n        ):\n            raise ValueError(\"Invalid operator usage.\")\n\n        open_parentheses = close_parentheses = 0\n        for i, char in enumerate(expression):\n            if char == \"(\":\n                open_parentheses += 1\n            elif char == \")\":\n                close_parentheses += 1\n            # Check for invalid operator sequences\n            if char in \"&|\" and i + 1 < len(expression) and expression[i + 1] in \"&|\":\n                raise ValueError(\n                    \"Invalid operator placement: operators cannot be adjacent.\"\n                )\n\n        if open_parentheses != close_parentheses:\n            raise ValueError(\"Missing or unbalanced parentheses in expression.\")\n\n        def evaluate_simple_expression(exp: str) -> List[str]:\n            \"\"\"Evaluate an expression without parentheses.\"\"\"\n\n            for or_segment in exp.split(\"|\"):\n                and_segment = or_segment.split(\"&\")\n                if all(elem.strip() in state for elem in and_segment):\n                    return [\n                        elem.strip() for elem in and_segment if elem.strip() in state\n                    ]\n            return []\n\n        def evaluate_expression(expression: str) -> List[str]:\n            \"\"\"Evaluate an expression with parentheses.\"\"\"\n\n            while \"(\" in expression:\n                start = expression.rfind(\"(\")\n                end = expression.find(\")\", start)","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/ScrapeGraphAI/Scrapegraph-ai/blob/532dfffbf6ee823a6c9cf8cfedc24a93bf026780/scrapegraphai/nodes/base_node.py#L175-L211","documentation":"Raised after the character scan when the number of '(' characters does not equal the number of ')' characters in the input-key expression. Parenthesized groups like \"(a | b) & c\" are supported, but they must balance.","triggerScenarios":"input=\"(key1 | key2 & key3\" (missing closing paren) or input=\"key1) & key2\" (stray closing paren).","commonSituations":"Manually nesting boolean groups and dropping a parenthesis; refactoring a complex expression and losing one side of a pair.","solutions":["Count opening and closing parentheses and add/remove the missing one","Prefer flatter expressions without parentheses when possible","Use a linter/editor paren-matching when writing complex input expressions"],"exampleFix":"// before\ninput=\"(parsed_docs | raw_docs & user_prompt\"\n// after\ninput=\"(parsed_docs | raw_docs) & user_prompt\"","handlingStrategy":"validation","validationCode":"def balanced(expr: str) -> bool:\n    return expr.count('(') == expr.count(')')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use editor paren matching when writing grouped expressions","Prefer flat expressions over nested parentheses"],"tags":["scrapegraphai","node-config","expression-parsing","parentheses"],"backgroundTag":"expression-syntax-invalid","analyzedSha":"532dfffbf6ee823a6c9cf8cfedc24a93bf026780","analyzedAt":"2026-08-28T15:19:38.821Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}