{"record":{"id":"7f481df0743ced25","repo":"ScrapeGraphAI/Scrapegraph-ai","slug":"empty-expression-7f481d","errorCode":null,"errorMessage":"Empty expression.","messagePattern":"Empty expression\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scrapegraphai/utils/parse_state_keys.py","lineNumber":37,"sourceCode":"\n    Returns:\n        list: A list of state keys that match the boolean expression,\n        ensuring each key appears only once.\n\n    Example:\n        >>> parse_expression(\"user_input & (relevant_chunks | parsed_document | document)\",\n                            {\"user_input\": None, \"document\": None,\n                            \"parsed_document\": None, \"relevant_chunks\": None})\n        ['user_input', 'relevant_chunks', 'parsed_document', 'document']\n\n    This function evaluates the expression to determine the\n    logical inclusion of state keys based on provided boolean logic.\n    It checks for syntax errors such as unbalanced parentheses,\n    incorrect adjacency of operators, and empty expressions.\n    \"\"\"\n\n    if not expression:\n        raise ValueError(\"Empty expression.\")\n\n    pattern = (\n        r\"\\b(\"\n        + \"|\".join(re.escape(key) for key in state.keys())\n        + r\")(\\b\\s*\\b)(\"\n        + \"|\".join(re.escape(key) for key in state.keys())\n        + r\")\\b\"\n    )\n    if re.search(pattern, expression):\n        raise ValueError(\"Adjacent state keys found without an operator between them.\")\n\n    expression = expression.replace(\" \", \"\")\n\n    if (\n        expression[0] in \"&|\"\n        or expression[-1] in \"&|\"\n        or \"&&\" in expression\n        or \"||\" in expression","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/ScrapeGraphAI/Scrapegraph-ai/blob/532dfffbf6ee823a6c9cf8cfedc24a93bf026780/scrapegraphai/utils/parse_state_keys.py#L19-L55","documentation":"ValueError from parse_expression: the boolean expression over state keys is empty (empty string or None). The function builds a regex from state keys, so at least one key/operator is required.","triggerScenarios":"Calling parse_expression('', state) or parse_expression(None, state) — e.g. an edge condition expression left blank in graph config.","commonSituations":"Optional conditional edges where the condition string comes from config and defaults to empty; template variables for the expression not filled in.","solutions":["Provide a non-empty expression of state keys joined by & (and) / | (or), e.g. 'key1 & key2'","Skip the conditional edge when the expression is empty rather than calling parse_expression"],"exampleFix":"# before\nkeys = parse_expression(cond_expr or '', state)\n# after\nif not cond_expr:\n    return []\nkeys = parse_expression(cond_expr, state)","handlingStrategy":"validation","validationCode":"if not expression or not expression.strip():\n    return []  # skip edge\nkeys = parse_expression(expression, state)","typeGuard":"def is_non_empty_expression(expr) -> bool:\n    return isinstance(expr, str) and len(expr.strip()) > 0","tryCatchPattern":"try:\n    keys = parse_expression(expr, state)\nexcept ValueError as e:\n    logger.warning(\"bad edge expression %r: %s\", expr, e)\n    keys = []","preventionTips":["Default condition expressions to a real key, never ''","Treat blank expressions as 'no edge' in config loaders","Unit-test all conditional edge expressions"],"tags":["validation","expression","state-keys"],"backgroundTag":"empty-argument","analyzedSha":"532dfffbf6ee823a6c9cf8cfedc24a93bf026780","analyzedAt":"2026-08-28T15:19:38.821Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}