节点发生error,如何如理

langgraph中,如果某个节点存在bug,如何让其跳转

在 LangGraph 里,节点有 bug/异常后想跳转,推荐做法是:不要让异常直接抛出到图外,而是在节点里 try/except 捕获,把错误写入 state,再用 conditional edgeCommand(goto=...) 路由到错误处理节点。LangGraph 的核心模型就是:node 负责更新状态,edge 决定下一步去哪;conditional edge 可以根据 state 动态选择下一个节点。(LangChain文档)

方式 1:用 state + conditional edge,最稳妥

from typing import TypedDict, Literal
from langgraph.graph import StateGraph, END

class State(TypedDict, total=False):
    input: str
    result: str
    error: str

def risky_node(state: State) -> State:
    try:
        # 这里是可能出 bug 的逻辑
        result = 1 / 0
        return {"result": str(result), "error": ""}
    except Exception as e:
        return {"error": f"{type(e).__name__}: {e}"}

def route_after_risky(state: State) -> Literal["handle_error", "next_node"]:
    if state.get("error"):
        return "handle_error"
    return "next_node"

def handle_error(state: State) -> State:
    print("捕获到错误:", state["error"])
    return state

def next_node(state: State) -> State:
    return {"result": "正常继续"}

builder = StateGraph(State)

builder.add_node("risky_node", risky_node)
builder.add_node("handle_error", handle_error)
builder.add_node("next_node", next_node)

builder.set_entry_point("risky_node")

builder.add_conditional_edges(
    "risky_node",
    route_after_risky,
    {
        "handle_error": "handle_error",
        "next_node": "next_node",
    },
)

builder.add_edge("handle_error", END)
builder.add_edge("next_node", END)

graph = builder.compile()

这个模式最清晰:
risky_node 只负责捕获错误并写入 state["error"]route_after_risky 负责判断跳到 handle_error 还是正常节点。

方式 2:节点里直接返回 Command(goto=...)

如果你希望节点自己决定跳转,可以用 Command。官方/社区文档里也提到,Command 可用于把状态更新和路由逻辑合在一起,类似“带 update 能力的 conditional edge”。(LangChain)

from typing import TypedDict, Literal
from langgraph.types import Command
from langgraph.graph import StateGraph, END

class State(TypedDict, total=False):
    result: str
    error: str

def risky_node(state: State) -> Command[Literal["handle_error", "next_node"]]:
    try:
        result = 1 / 0
        return Command(
            update={"result": str(result)},
            goto="next_node",
        )
    except Exception as e:
        return Command(
            update={"error": f"{type(e).__name__}: {e}"},
            goto="handle_error",
        )

def handle_error(state: State) -> State:
    return {"result": "已进入错误处理节点"}

def next_node(state: State) -> State:
    return {"result": "正常执行"}

builder = StateGraph(State)

builder.add_node("risky_node", risky_node)
builder.add_node("handle_error", handle_error)
builder.add_node("next_node", next_node)

builder.set_entry_point("risky_node")

# 注意:使用 Command(goto=...) 时,不要再给 risky_node 添加普通 add_edge
builder.add_edge("handle_error", END)
builder.add_edge("next_node", END)

graph = builder.compile()

关键点:如果节点返回 Command(goto=...),最好不要同时给这个节点配置固定 add_edge("risky_node", "...")。社区里有人遇到过 Command(goto=...) 和静态边同时存在时,错误处理节点和普通后续节点都被执行的问题;一种解决方式是该节点的路由全交给 Command 或 conditional edge。(GitHub)

方式 3:瞬时错误用 retry,不一定要跳转

如果是网络超时、rate limit、临时 API 失败,不一定马上跳到 error node,可以用 retry policy。LangGraph 文档把错误处理分成不同类型:临时错误适合系统自动重试,而需要人工修复或业务判断的错误才更适合路由到专门节点。(LangChain文档)

实践建议

一般我会这样选:

可恢复的临时错误 → RetryPolicy
业务错误/校验失败 → 写入 state,然后 conditional edge 跳转
节点内部异常但要立刻改道 → Command(update=..., goto=...)
需要人工介入 → interrupt / human-in-the-loop 模式

最推荐的生产写法是 方式 1:try/except + state.error + conditional edge,因为它最容易调试、最不容易和固定边冲突。

posted @ 2026-05-25 19:47  X1OO  阅读(17)  评论(0)    收藏  举报