ScrapeGraphAI/Scrapegraph-ai · error · ValueError
node_type must be 'node' or 'conditional_node', got '{node_t
Error message
node_type must be 'node' or 'conditional_node', got '{node_type}' What it means
BaseNode.__init__ validates its node_type argument against the two allowed values ('node' and 'conditional_node'); anything else — including None, 'Node', or a custom string — raises immediately when the node object is constructed. node_type determines how BaseGraph routes execution, so it cannot be free-form.
Source
Thrown at scrapegraphai/nodes/base_node.py:65
def __init__(
self,
node_name: str,
node_type: str,
input: str,
output: List[str],
min_input_len: int = 1,
node_config: Optional[dict] = None,
):
self.node_name = node_name
self.input = input
self.output = output
self.min_input_len = min_input_len
self.node_config = node_config
self.logger = get_logger()
if node_type not in ["node", "conditional_node"]:
raise ValueError(
f"node_type must be 'node' or 'conditional_node', got '{node_type}'"
)
self.node_type = node_type
@abstractmethod
def execute(self, state: dict) -> dict:
"""
Execute the node's logic based on the current state and update it accordingly.
Args:
state (dict): The current state of the graph.
Returns:
dict: The updated state after executing the node's logic.
"""
pass
View on GitHub (pinned to 532dfffbf6)
Solutions
- Use node_type='node' for standard nodes and 'conditional_node' for nodes that return the next node's name.
- Usually the right fix is to inherit from Node or ConditionalNode in scrapegraphai.nodes, which set node_type for you.
- Check for typos/case if passing a computed value.
Example fix
# before
class MyNode(BaseNode):
def __init__(self, **kwargs):
super().__init__(node_type='conditional', **kwargs)
# after
from scrapegraphai.nodes import ConditionalNode
class MyNode(ConditionalNode):
pass Defensive patterns
Strategy: validation
Validate before calling
assert node_type in ('node', 'conditional_node'), f"invalid node_type {node_type!r}" Type guard
def is_valid_node_type(t: str) -> bool:
return t in ('node', 'conditional_node') Try / catch
try:
n = MyNode(node_type=nt, ...)
except ValueError as e:
if 'node_type must be' in str(e):
nt = 'conditional_node' if is_router else 'node'
n = MyNode(node_type=nt, ...)
else:
raise Prevention
- Inherit from Node / ConditionalNode instead of BaseNode directly.
- Never make node_type configurable/free-form in custom node factories.
- Cover custom nodes with a construction unit test.
When it happens
Trigger: Subclassing BaseNode (or ConditionalNode) and passing node_type='custom' / 'router' / 'conditionalNode'; passing node_type=None in a custom constructor; calling BaseNode(...) directly for testing.
Common situations: Writing custom nodes for the first time and guessing the type string; case mismatches ('Conditional_Node'); refactoring where a variable holding the type is unset.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Error instancing model: {e}
- Error parsing input keys for {self.node_name}
- {self.node_name} requires at least {self.min_input_len} inpu
- Empty expression.
AI-assisted analysis of ScrapeGraphAI/Scrapegraph-ai@532dfffbf6 (2026-08-28).
Data as JSON: /api/errors/4147cdf9a4718192.
Report an issue: GitHub.