Node function signature wrong: missing state arg
Why this matters
This is the #1 runtime error beginners hit in langgraph. Your node won't be called correctly, and the error message is cryptic. Understanding the contract prevents hours of debugging.
Explanation
The problem: In langgraph, every node function is a callable that receives the current state and returns an updated state (or None). If your function signature doesn't accept the state parameter, langgraph will not pass it correctly, and your node will execute in an undefined way or fail. Mechanically: When you call graph.invoke({'key': 'value'}), langgraph walks the graph and invokes each node with the state dict as the first positional argument. If your node function is defined as def my_node(): instead of def my_node(state):, the state dict will be passed to a function that doesn't accept it, causing a TypeError. When to use correct signatures: Always define node functions with (state: State) or (state) as the first parameter, where State is your state class or a dict annotation. The second parameter can optionally be config: RunnableConfig for advanced use cases, but state is mandatory.
Analogy
Think of langgraph nodes like API endpoints. If your endpoint signature is <code>def handler()</code> with no parameters, the router will try to pass request data to it anyway: and it will break. You need <code>def handler(request)</code> to accept what's being sent.
Code
from langgraph.graph import StateGraph, START, END
from langgraph.types import StateSnapshot
from typing_extensions import TypedDict
class State(TypedDict):
count: int
message: str
def node_wrong(state):
"""This function signature is CORRECT — it accepts state."""
return {"count": state["count"] + 1}
def node_broken():
"""This function signature is WRONG — it does NOT accept state."""
return {"count": 5}
graph = StateGraph(State)
graph.add_node("increment", node_wrong)
graph.add_node("broken", node_broken)
graph.add_edge(START, "increment")
graph.add_edge("increment", "broken")
graph.add_edge("broken", END)
compiled = graph.compile()
try:
result = compiled.invoke({"count": 0, "message": "start"})
print(f"Result: {result}")
except TypeError as e:
print(f"Error caught: {e}") Error caught: node_broken() takes 0 positional arguments but 1 was given
What just happened?
We defined two nodes: one with the correct signature (<code>node_wrong(state)</code>) and one with a broken signature (<code>node_broken()</code>). When langgraph executed the graph, it invoked <code>node_broken</code> with the state dict as an argument, but the function accepts zero arguments. Python raised a TypeError. The correct node would have executed fine.
Common gotcha
The error message is confusing because it says 'takes 0 positional arguments but 1 was given': you won't immediately recognize that 'the 1' is the state dict. Beginners often think they're passing the wrong number of arguments to the node call itself, when really the problem is the function definition.
Error recovery
TypeError: takes 0 positional arguments but 1 was givenTypeError: takes 1 positional argument but 2 were givenNameError: name 'state' is not defined inside nodeExperienced dev note
In synchronous nodes, you must return a dict (even if empty `{}`). In async nodes with `@langgraph.function_node` decorator, the return signature is the same. But here's what senior devs know: if you use Annotated types in your node definition (like def my_node(state: Annotated[State, ...])), you're being explicit about the contract, and IDEs will catch signature errors earlier. Always use Annotated for state type hints if your codebase supports it: it's a micro-investment that saves debugging.
Check your understanding
Why does the error message say 'takes 0 positional arguments but 1 was given' instead of saying 'missing required state parameter'? What is the '1' that was given?
Show answer hint
The '1' is the state dict that langgraph is passing to your node function automatically. The error is coming from Python's function call mechanism, not from langgraph: so it reports what Python sees (a call with 1 argument to a function defined with 0 parameters), not what langgraph intended.