Fix LangGraph InvalidUpdateError: Must write to at least one of ['input', 'plan', 'past_steps', 'response']
Error message
langgraph.errors.InvalidUpdateError: Must write to at least one of ['input', 'plan', 'past_steps', 'response']The langgraph.errors.InvalidUpdateError: Must write to at least one of ['input', 'plan', 'past_steps', 'response'] error occurs when a LangGraph node function returns a dictionary that does not include any of the keys expected by the graph's state schema. The most common cause is a mismatch between the keys your node writes and the keys defined in your state TypedDict, often because a state field is marked as Optional but the node fails to include it, or because the node returns an empty dictionary or a dictionary with keys that are not in the allowed set.
What Causes This Error
According to the GitHub issue and its solution comment, this error has two primary causes:
-
State fields defined as
Optionalwithout a default value: When you define a LangGraph state using a TypedDict and mark a field asOptional[str](or any otherOptionaltype), LangGraph expects that field to be present in the state update dictionary. If your node function returns a dictionary that does not include that field, LangGraph raises theInvalidUpdateError. This is the most common cause reported in the issue. The user in the issue was using a state likePlanExecutewith fieldsinput,plan,past_steps, andresponse, and one or more of these fields was likely defined asOptionalwithout a default value, causing the error when the node only wrote to a subset of them. -
Node returns a dictionary with keys not in the state schema: If your node function returns a dictionary that contains keys that are not part of the state's TypedDict, LangGraph will also raise this error. The error message lists the allowed keys:
['input', 'plan', 'past_steps', 'response']. If your node returns something like{"past_steps": [...], "extra_key": "value"}, the error will occur becauseextra_keyis not in the allowed set.
How to Fix It
Solution 1: Ensure all state fields have default values (Recommended)
This fix comes from the solution comment by Halil3509 in the GitHub issue. If you have defined your state with Optional fields, you must provide a default value for each field. For example, instead of:
from typing import TypedDict, Optional
class PlanExecute(TypedDict):
input: str
plan: list[str]
past_steps: list[tuple[str, str]]
response: Optional[str]
Define it with a default value:
from typing import TypedDict, Optional
class PlanExecute(TypedDict):
input: str
plan: list[str]
past_steps: list[tuple[str, str]]
response: Optional[str] = None
Alternatively, you can use a total=False TypedDict or a dataclass with defaults. The key point is that every field in the state must have a default value, or your node must always write to every field. In the example code from the issue, the execute_step node only writes to past_steps:
async def execute_step(state: PlanExecute):
objective = state["input"]
task = state["plan"][0]
agent_response = await agent_executor.ainvoke({"objective": objective, "input": task, "chat_history": []})
return {
"past_steps": [(task, agent_response["result"])],
}
If response is Optional[str] without a default, this node will fail because it does not write to response. Adding a default value of None to response fixes the issue.
Solution 2: Write to all required state keys in every node
If you cannot or do not want to add default values to your state fields, you must ensure that every node function returns a dictionary that includes all keys defined in the state TypedDict. For the PlanExecute state, that means every node must write to input, plan, past_steps, and response. For example:
async def execute_step(state: PlanExecute):
objective = state["input"]
task = state["plan"][0]
agent_response = await agent_executor.ainvoke({"objective": objective, "input": task, "chat_history": []})
return {
"input": state["input"],
"plan": state["plan"],
"past_steps": [(task, agent_response["result"])],
"response": None, # or some default
}
This approach is more verbose but works if you prefer not to use defaults. Note that if you have many nodes, this can become repetitive and error-prone.
Solution 3: Check for extra keys in the returned dictionary
If you are sure your state fields have defaults, verify that your node is not returning extra keys. For instance, if your node returns:
return {
"past_steps": [(task, agent_response["result"])],
"unexpected_key": "value"
}
LangGraph will raise the InvalidUpdateError because unexpected_key is not in ['input', 'plan', 'past_steps', 'response']. Remove any keys that are not part of the state schema.
If Nothing Works
If the above solutions do not resolve the error, consider the following escalation paths:
- Check your LangGraph version: Ensure you are using the latest version of LangGraph. The bug may have been fixed in a newer release. Run
pip install --upgrade langgraph. - Open a GitHub issue: The original issue was filed on the LangGraph GitHub repository. If you have a minimal reproducible example, open a new issue at https://github.com/langchain-ai/langgraph/issues with a descriptive title, the exact error message, and your code.
- Search the LangGraph documentation: The official documentation at https://langchain-ai.github.io/langgraph/ has a search feature. Look for "InvalidUpdateError" or "state schema" for more examples.
- Workaround: If you are blocked, consider restructuring your graph to use a single node that writes to all state keys, or use a reducer that merges state updates. For example, you can use a custom reducer function to handle partial updates.
How to Prevent It
To avoid this error in the future:
- Always provide default values for
Optionalfields in your state TypedDict. This is the simplest and most reliable way to prevent the error. UseOptional[str] = NoneorOptional[list] = [](but be careful with mutable defaults; useNoneand handle it in your code). - Design your nodes to write only to the keys they need to update, but ensure that all keys have defaults. This keeps your code clean and avoids the error.
- Use a consistent state schema across all nodes. If you add a new field to the state, update all nodes that might run after it to include that field in their return dictionaries.
- Test your graph with a simple linear flow first before adding complex branching or cycles. This helps catch state mismatches early.
- Use type hints and static analysis (e.g., mypy) to catch missing keys in your node return dictionaries before runtime.
The #1 AI Newsletter
The most important ai updates, guides, and fixes — one weekly email.
No spam, unsubscribe anytime. Privacy policy
Sources & References
This page was researched from 2 independent sources, combined and verified for completeness.
- 1.
- 2.Solution comment by Halil3509 (0 reactions)GitHub issue
Related Error Solutions
Keep exploring
Latest AI answers
Skip the manual work
Ready-made AI workflows and automation templates — import and run instead of building from scratch.