{"record":{"id":"980d6bc4fcd1b23a","repo":"ScrapeGraphAI/Scrapegraph-ai","slug":"empty-expression","errorCode":null,"errorMessage":"Empty expression.","messagePattern":"Empty expression\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scrapegraphai/nodes/base_node.py","lineNumber":154,"sourceCode":"    def _parse_input_keys(self, state: dict, expression: str) -> List[str]:\n        \"\"\"\n        Parses the input keys expression to extract\n        relevant keys from the state based on logical conditions.\n        The expression can contain AND (&), OR (|), and parentheses to group conditions.\n\n        Args:\n            state (dict): The current state of the graph.\n            expression (str): The input keys expression to parse.\n\n        Returns:\n            List[str]: A list of key names that match the input keys expression logic.\n\n        Raises:\n            ValueError: If the expression is invalid or if no state keys match the expression.\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(\n                \"Adjacent state keys found without an operator between them.\"\n            )\n\n        expression = expression.replace(\" \", \"\")\n\n        if (\n            expression[0] in \"&|\"\n            or expression[-1] in \"&|\"","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/ScrapeGraphAI/Scrapegraph-ai/blob/532dfffbf6ee823a6c9cf8cfedc24a93bf026780/scrapegraphai/nodes/base_node.py#L136-L172","documentation":"The lowest-level check in _parse_input_keys: the node's input expression is empty/None, so there is nothing to match against state keys and a ValueError('Empty expression.') is thrown. It surfaces wrapped by get_input_keys as 'Error parsing input keys for {node_name}'.","triggerScenarios":"Constructing a node with input='' or input=None (e.g. a custom node whose input config was not populated, or f-string config producing an empty string) and then executing it.","commonSituations":"Custom nodes where the input attribute is built from a config value that is missing; dynamically generated node definitions with a blank input field; refactoring that drops the input argument.","solutions":["Set a non-empty input expression on the node, e.g. input='doc' or input='user_prompt| doc'.","If the input is built from config, default it: node_input = cfg.get('input') or 'doc'.","Add a constructor-level assertion/guard so misconfiguration fails fast with a clearer message."],"exampleFix":"# before\nmy_node = MyNode(input='', node_config=cfg)\n\n# after\nmy_node = MyNode(input='doc', node_config=cfg)","handlingStrategy":"validation","validationCode":"assert node.input, f'{type(node).__name__} needs a non-empty input expression like \"doc\" or \"user_prompt| doc\"'","typeGuard":"def has_input_expression(node) -> bool:\n    return bool(getattr(node, 'input', None))","tryCatchPattern":"try:\n    final_state, info = graph.execute(inputs)\nexcept ValueError as e:\n    if 'Empty expression' in str(e.__cause__ or ''):\n        node.input = 'doc'\n        final_state, info = graph.execute(inputs)\n    else:\n        raise","preventionTips":["Always pass a concrete input expression when constructing nodes.","Default dynamically built inputs: cfg.get('input') or 'doc'.","Assert non-empty input in custom node constructors."],"tags":["input-parsing","empty-string","node","configuration"],"backgroundTag":"empty-input-expression","analyzedSha":"532dfffbf6ee823a6c9cf8cfedc24a93bf026780","analyzedAt":"2026-08-28T15:19:38.821Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}