-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Type of issue
issue / bug
Language
JavaScript
Description
Documentation Error: gradeDocuments node returns string instead of state update object in Agentic RAG tutorial
Summary
The Build a custom RAG agent with LangGraph tutorial contains a critical error in the gradeDocuments node implementation. The node is defined to return a string ("generate" or "rewrite"), but StateGraph nodes must return objects or Command instances to update state. This code will throw an InvalidUpdateError at runtime.
Location
Section 4: "Grade documents" in the Agentic RAG tutorial
Current (Incorrect) Code
const gradeDocuments: GraphNode<typeof State> = async (state) => {
const model = new ChatOpenAI({
model: "gpt-4.1",
temperature: 0,
}).withStructuredOutput(gradeDocumentsSchema);
const score = await prompt.pipe(model).invoke({
question: state.messages.at(0)?.content,
context: state.messages.at(-1)?.content,
});
if (score.binaryScore === "yes") {
return "generate"; // β ERROR: Nodes cannot return primitives
}
return "rewrite"; // β ERROR: Nodes cannot return primitives
}And the conditional edge tries to read from state.messages:
.addConditionalEdges(
"gradeDocuments",
(state) => {
const lastMessage = state.messages.at(-1);
return lastMessage.content === "generate" ? "generate" : "rewrite"; // β This won't work
}
)Why This is Wrong
- StateGraph nodes must return objects or Commands: According to the source code in
libs/langgraph-core/src/graph/state.ts(lines 1379-1389), the_getUpdatesfunction validates node return values and throws anInvalidUpdateErrorif a primitive type is returned:
} else {
const typeofInput = Array.isArray(input) ? "array" : typeof input;
throw new InvalidUpdateError(
`Expected node "${nodeKey.toString()}" to return an object or an array containing at least one Command object, received ${typeofInput}`,
{
lc_error_code: "INVALID_GRAPH_NODE_RETURN_VALUE",
}
);
}-
No automatic wrapping: LangGraph does not automatically wrap primitive return values into state updates. The string will not magically appear in
state.messages[].content. -
Confusion between nodes and conditional edges: The documentation appears to confuse node functions (which update state) with conditional edge routing functions (which return strings to indicate the next node).