LangGraph 错误码完全指南:32 个高频错误中文解读与解决方案

15 阅读11分钟

错误码分类导航

子模块高频错误数长尾错误数跳转
langgraph.errors91→ 查看
langgraph.checkpoint14→ 查看
Graph state(state 字段相关)24→ 查看
LLM / API03→ 查看
Routing / Edge03→ 查看
Pregel / Concurrency03→ 查看
Tools / Function02→ 查看

一、langgraph.errors 子模块(高频错误)

GraphRecursionError

错误现象:程序抛出 GraphRecursionError: Recursion limit reached,图执行中断。

根因:图的执行步数超过了 recursion_limit(默认 25 步)。最常见的原因是条件边逻辑有 bug,导致图在几个节点之间循环。

解决方案

from langgraph.graph import StateGraph, END

class State(TypedDict):
    step_count: int
    output: str

def step(state: State) -> dict:
    return {"step_count": state["step_count"] + 1}

def should_continue(state: State) -> str:
    if state["step_count"] >= 5:
        return "end"
    return "continue"

graph = StateGraph(State)
graph.add_node("step", step)
graph.add_conditional_edges("step", should_continue, {
    "continue": "step",
    "end": END
})
# 关键:设置 recursion_limit
graph = graph.compile(recursion_limit=50)

排查技巧:在条件边函数里加 print(f"step={state['step_count']} route={route}") 观察路由循环。


InvalidUpdateError

错误现象InvalidUpdateError: Invalid update at node xxx,schema 校验失败。

根因:节点函数返回的 dict 包含了 State schema 中未声明的字段,或字段类型与 TypedDict / Pydantic 定义不匹配。

解决方案

from typing import TypedDict

class OrderState(TypedDict):
    order_id: str
    status: str
    total: float

# 错误写法:返回了 schema 中没有的字段
def bad_node(state: OrderState) -> dict:
    return {"order_id": state["order_id"], "status": "paid",
            "total": 99.0, "extra_field": "oops"}  # InvalidUpdateError!

# 正确写法:只返回 schema 中有的字段
def good_node(state: OrderState) -> dict:
    return {"status": "paid", "total": 99.0}

GraphInterrupt

错误现象:执行暂停,抛出 GraphInterrupt(注意:这是正常流程,不是错误)。

根因:代码中显式调用了 interrupt(value),用于 Human-in-the-loop 场景。

解决方案:用 Command(resume=value) 恢复执行:

from langgraph.types import interrupt, Command

def approval_node(state: State) -> Command:
    decision = interrupt("请审批该请求")
    if decision["approved"]:
        return Command(goto="process", update={"status": "approved"})
    return Command(goto="reject", update={"status": "rejected"})

NodeInterrupt

错误现象:节点内部抛出 NodeInterrupt,执行暂停在该节点。

根因:节点函数内部调用了 interrupt(),且未提供 resume 值。

解决方案:与 GraphInterrupt 相同,使用 Command(resume=...) 恢复。确保上游有 interrupt_beforeinterrupt_after 配置。


NodeCancelledError

错误现象NodeCancelledError: Node execution was cancelled

根因:节点执行被外部中止(任务取消 / 服务 shutdown / 超时 kill)。

解决方案

import signal

def timeout_handler(signum, frame):
    raise TimeoutError("Node execution timed out")

# 在节点函数中设置超时
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(25)  # 25 秒超时
try:
    result = long_running_task()
finally:
    signal.alarm(0)

NodeTimeoutError

错误现象NodeTimeoutError: Node timed out after 30s

根因:节点执行时间超过配置的 timeout(默认 30 秒)。常见于调用外部 API 或大模型推理。

解决方案

import httpx

async def call_external_api(state: State, timeout: float = 60.0) -> dict:
    async with httpx.AsyncClient(timeout=timeout) as client:
        resp = await client.post("https://api.example.com/process", json=state)
        return {"result": resp.json()}

# 或在 graph.compile 时设置节点级 timeout
graph = graph.compile(
    checkpointer=memory,
    node_config={"slow_node": {"timeout": 120}}
)

ParentCommand

错误现象ParentCommand: Command received from subgraph

根因:subgraph 内部通过 Command(goto=...) 向 parent graph 发送了跨层通信指令。这是 LangGraph 的正常机制,但如果 parent 没有正确处理会抛出异常。

解决方案:确保 parent graph 中对应的节点能处理 subgraph 返回的 Command:

# parent graph 中
graph.add_edge("subgraph_node", "handle_result")

def handle_result(state: State) -> dict:
    # subgraph 可能通过 Command 返回更新
    return state

EmptyInputError

错误现象EmptyInputError: Input is empty or all fields are None

根因app.invoke({}) 传入的 state 为空字典,或所有必填字段都为 None。

解决方案

from pydantic import ValidationError

class RequiredState(TypedDict):
    user_input: str  # 必填

# 错误写法
result = app.invoke({})  # EmptyInputError

# 正确写法:提供必填字段
result = app.invoke({"user_input": "你好"})

TaskNotFound

错误现象TaskNotFound: task_id xxx not found in state

根因:在多任务并发场景中,引用了 state 中不存在的 task_id。

解决方案:确保 task_id 的创建和引用在同一个 graph 执行周期内,或在 checkpointer 中正确恢复。


GraphDrained

错误现象GraphDrained: All tasks consumed, graph is drained

根因:图排空(所有任务消费完毕),通常发生在 Signal GEN = SIGTERM 触发的优雅退出时。

解决方案:这是正常退出信号,无需处理。如需重启,重新 invoke 即可。


二、langgraph.checkpoint 子模块

EmptyChannelError

错误现象EmptyChannelError: Channel is empty,checkpoint 写入失败。

根因:某个 channel 在本轮执行中没有产生任何更新(值未变化),写 checkpoint 时触发空值校验。

解决方案

from langgraph.channels import LastValue

# 使用 LastValue channel 允许空值覆盖
graph.add_node("update", update_node, output=LastValue("field"))

CheckpointNotFound

错误现象CheckpointNotFound: thread_id xxx not found in storage

根因:指定的 thread_id 在 checkpointer 存储中不存在,可能原因:

  • thread_id 拼写错误
  • checkpoint 已被清理(TTL 过期)
  • 数据库连接的是不同的环境(dev / prod 混淆)

解决方案

# 确认 thread_id 格式
config = {"configurable": {"thread_id": "user-123-session-1"}}

# 检查 checkpointer 连接
from langgraph.checkpoint.postgres import PostgresSaver
checkpointer = PostgresSaver.from_conn_string("postgresql://user:pass@host/db")
print(checkpointer.conn.info)  # 确认连接的数据库

SerializationError-checkpoint

错误现象SerializationError: Failed to serialize checkpoint(msgpack / pickle 错误)。

根因:State 中包含不可序列化的对象(如 datetime、自定义类、函数)。

解决方案:State 中只使用基本类型(str / int / float / bool / list / dict):

from datetime import datetime
from pydantic import BaseModel

# 错误:State 中包含 datetime
class BadState(TypedDict):
    created_at: datetime  # msgpack 无法序列化

# 正确:转成 ISO 字符串
class GoodState(TypedDict):
    created_at: str  # "2026-09-08T12:00:00"

CheckpointerConnectionError

错误现象CheckpointerConnectionError: could not connect to postgres

根因:Postgres / Sqlite checkpointer 连接失败。

解决方案

# 检查 Postgres 服务状态
pg_isready -h localhost -p 5432

# 检查连接字符串
echo $POSTGRES_CONNECTION_STRING
# 期望:postgresql://user:pass@host:5432/dbname

BinaryOperatorAggregateError

错误现象BinaryOperatorAggregateError: duplicate keys in state aggregator

根因:多个节点同时更新同一个字段,且 reducer 不支持合并(如两个节点都 return {"messages": [...]} 但 messages 使用了字典合并而非列表追加)。

解决方案:使用 Annotated[list, add_messages] 定义消息字段:

from typing import Annotated
from langgraph.graph.message import add_messages

class State(TypedDict):
    # 正确:多个节点可以安全追加消息
    messages: Annotated[list, add_messages]

三、Graph state 子模块(本项目实战高频)

ImportError-version-mismatch

错误现象ImportError: cannot import name 'xxx' from 'langgraph'

根因langgraphlangchain-core 版本不匹配。LangGraph 0.6.11 要求 langchain-core>=0.3.0

解决方案

# 统一升级到兼容版本
pip install --upgrade langgraph==0.6.11 langchain-core>=0.3.0

# 验证版本
python3 -c "import langgraph, langchain_core; print(langgraph.__version__, langchain_core.__version__)"

InvalidUpdateError-state-field-mismatch

错误现象InvalidUpdateError: Field type mismatch for 'xxx'

根因:State TypedDict 字段类型与实际返回值不符(如字段定义 int,返回了 str)。

解决方案

from typing import TypedDict

class State(TypedDict):
    count: int

# 错误:count 应该是 int,但返回了 str
def bad_node(state: State) -> dict:
    return {"count": "10"}  # InvalidUpdateError

# 正确:类型匹配
def good_node(state: State) -> dict:
    return {"count": 10}

KeyError-state-field-missing

错误现象KeyError: 'field_name'

根因:节点函数访问了 state 中不存在的字段。常见于 TypedDict 拼写错误或字段被条件跳过。

解决方案:使用 .get() 安全访问,或确保所有路径都初始化该字段:

def safe_node(state: State) -> dict:
    # 错误写法
    value = state["missing_field"]  # KeyError

    # 正确写法:用 get 提供默认值
    value = state.get("missing_field", "default")
    return {"field": value}

TypeError-node-signature

错误现象TypeError: node() missing 1 required positional argument: 'state'

根因:节点函数签名错误,缺少 state 参数或参数名不匹配。

解决方案

# 错误写法
def my_node():  # 缺少 state 参数
    return {"result": "ok"}

# 正确写法
def my_node(state: State) -> dict:
    return {"result": state.get("input", "")}

ValidationError-pydantic-state

错误现象ValidationError: value is not a valid integer(Pydantic 校验失败)。

根因:State 使用 Pydantic BaseModel 定义,但节点返回值不符合字段类型或约束。

解决方案

from pydantic import BaseModel, Field

class State(BaseModel):
    name: str = Field(min_length=1, max_length=100)
    age: int = Field(ge=0, le=150)

# 确保节点返回符合 Pydantic 约束
def good_node(state: State) -> dict:
    return {"name": state.name.strip(), "age": state.age}

StateGraphBuildError

错误现象StateGraphBuildError: Graph structure is invalid

根因:StateGraph 构建期错误,常见原因:

  • 节点未定义就引用
  • 缺少入口点
  • 存在不可达节点

解决方案

from langgraph.graph import StateGraph, END

graph = StateGraph(State)

# 错误:add_edge 引用了不存在的节点
# graph.add_edge("unknown_node", END)  # StateGraphBuildError

# 正确:先 add_node,再 add_edge
graph.add_node("real_node", real_function)
graph.add_edge("real_node", END)
graph.set_entry_point("real_node")

四、LLM / API 子模块

TimeoutError-llm-call

错误现象TimeoutError: Request timed out after 60s

根因:LLM API 调用超时。原因可能是网络延迟、模型服务繁忙、prompt 过长。

解决方案

import httpx

client = httpx.AsyncClient(timeout=httpx.Timeout(120.0, connect=10.0))
resp = await client.post(
    "https://api.minimaxi.com/v1/chat/completions",
    json={"model": "MiniMax-M2.7", "messages": [...]},
    headers={"Authorization": f"Bearer {api_key}"}
)

RetryExhausted

错误现象RetryExhausted: Max retries exceeded

根因:LLM API 连续多次调用失败(网络抖动 / 限流 / 服务不可用),重试耗尽。

解决方案

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3), wait=wait_exponential(min=1, max=10))
def call_llm_with_retry(prompt: str) -> str:
    return llm.invoke(prompt).content

MessageConversionError

错误现象MessageConversionError: Failed to convert messages

根因:LangChain 内部消息格式与 OpenAI / MiniMax API 格式不兼容,常见于混合使用不同厂商的 message 格式。

解决方案:统一使用 langchain_core.messages 标准格式:

from langchain_core.messages import HumanMessage, SystemMessage, AIMessage

messages = [
    SystemMessage(content="你是一个有帮助的助手。"),
    HumanMessage(content="LangGraph 怎么入门?"),
    AIMessage(content="可以从官方 quickstart 开始..."),
    HumanMessage(content="能给我一个代码示例吗?"),
]
# LangChain 会自动转换为目标 API 的格式

五、Routing / Edge 子模块

ConditionalEdgeMissingRoute

错误现象ConditionalEdgeMissingRoute: No route found for 'xxx'

根因:条件边函数返回了一个不在路由映射表中的值。

解决方案

# 错误写法
def route(state: State) -> str:
    return "unknown_destination"  # 不在映射表中

graph.add_conditional_edges("node", route, {
    "tech": "tech_agent",
    "biz": "biz_agent"
    # "unknown_destination" 缺失!
})

# 正确写法:覆盖所有可能返回值
graph.add_conditional_edges("node", route, {
    "tech": "tech_agent",
    "biz": "biz_agent",
    "unknown_destination": "fallback_agent",
    "END": END
})

SubgraphInterruptError

错误现象SubgraphInterruptError: Interrupt in subgraph not handled

根因:subgraph 内部触发了 interrupt(),但 parent graph 没有配置对应的 interrupt_before / interrupt_after

解决方案

# parent graph 中,允许 subgraph 在 "approval" 节点前中断
graph.add_node("subgraph", subgraph_app, interrupt_before=["approval"])

StreamConsumerError

错误现象StreamConsumerError: Generator was not fully consumed

根因:调用 graph.stream() 时,没有迭代完整个 generator 就提前退出了(如 break 或 return)。

解决方案

# 错误写法
for event in app.stream(input):
    if some_condition:
        break  # generator 未消费完,抛出 StreamConsumerError

# 正确写法:消费完整 generator,或使用 list() 缓存
events = list(app.stream(input))
for event in events:
    process(event)

六、Pregel / Concurrency 子模块

RecursionLimitHit

错误现象RecursionLimitHit: Pregel recursion limit exceeded

根因:与 GraphRecursionError 类似,但发生在 Pregel 运行时层。Pregel 是 LangGraph 底层的 BSP(Bulk Synchronous Parallel)执行引擎。

解决方案:与 GraphRecursionError 相同——检查条件边环路,避免无限循环。


PregelTimeoutError

错误现象PregelTimeoutError: Pregel execution timed out

根因:Pregel 整体执行超时(包括所有节点执行 + 调度总时长)。通常发生在图非常复杂或某个节点阻塞时。

解决方案

# 增大超时配置
app = graph.compile(
    checkpointer=memory,
    config={"recursion_limit": 100, "timeout": 300}
)

AsyncEventLoopError

错误现象AsyncEventLoopError: async function called from sync context

根因:在同步 pytest fixture 中直接调用 async 函数,或在 sync Playwright 测试中调用 async LangGraph 方法。

解决方案:统一使用 asyncio.run()anyio

import asyncio

# 正确:在 sync 函数中运行 async 代码
def sync_wrapper():
    result = asyncio.run(async_langgraph_call())
    return result

七、Tools / Function 子模块

ToolNotFound

错误现象ToolNotFound: tool 'xxx' not found

根因tool_calls 引用的工具名称不在已绑定的工具列表中。

解决方案

from langchain_core.tools import tool

@tool
def search(query: str) -> str:
    """搜索网页。"""
    return f"结果:{query}"

# 绑定工具时确保名称一致
llm_with_tools = llm.bind_tools([search])

# tool_calls 中的 name 必须匹配 @tool 装饰的函数名
# {"name": "search", "arguments": {"query": "LangGraph"}}  ✓
# {"name": "web_search", ...}  ✘ ToolNotFound

ConfigNotFoundError

错误现象ConfigNotFoundError: RunnableConfig missing 'xxx'

根因RunnableConfig 中缺少必要字段(如 configurable["thread_id"])。

解决方案

# 错误写法
app.invoke({"messages": [...]})  # 缺少 thread_id

# 正确写法
config = {
    "configurable": {
        "thread_id": "user-123",
        "checkpoint_ns": "default"
    }
}
app.invoke({"messages": [...]}, config=config)

八、常见排查流程图

流程图(Mermaid 语法,知乎支持)

flowchart TD
    A[程序抛出异常] --> B{异常类型}
    B -->|GraphRecursionError| C[检查条件边环路增大 recursion_limit]
    B -->|InvalidUpdateError| D[检查 Node 返回值对齐 State schema]
    B -->|NodeTimeoutError| E[增大 timeout改用异步节点]
    B -->|CheckpointNotFound| F[检查 thread_id确认 checkpointer 连接]
    B -->|CheckpointerConnectionError| G[检查 Postgres/Sqlite服务状态]
    B -->|其他错误| H[查阅完整错误码库errors-zh/INDEX.md]
    C --> I[重新运行验证]
    D --> I
    E --> I
    F --> I
    G --> I
    H --> I
    I --> J{是否解决}
    J -->|否| K[搜索 GitHub Issueslangchain-ai/langgraph]
    J -->|是| L[✅ 问题已解决]

文字版流程图(公众号不支持 Mermaid)

  1. 程序抛出异常 → 先看异常类型(类名)
  2. GraphRecursionError → 检查条件边是否形成环路 → 增大 recursion_limit → 重新运行
  3. InvalidUpdateError → 检查抛出异常的 Node → 对比返回值与 State schema → 修正字段名/类型 → 重新运行
  4. NodeTimeoutError → 检查该 Node 是否调用外部 API → 增大 timeout 或改用异步 → 重新运行
  5. CheckpointNotFound / CheckpointerConnectionError → 检查 thread_id 是否正确 → 检查 Postgres/Sqlite 连接 → 重新运行
  6. 其他错误 → 查阅完整错误码库 ../errors-zh/INDEX.md → 搜索 GitHub Issues
  7. 仍未解决 → 在 LangGraph GitHub Discussions 提问

九、免责声明

本文基于 LangGraph 0.6.11 版本编写,错误码及其解决方案可能随版本迭代而变化。LangGraph 迭代速度较快,请以 官方文档官方 GitHub 仓库 为准。

完整错误码库(32 个错误码,含详细代码示例)见交付包内 errors-zh/INDEX.md


*本文由裕普智汇 AI 智能体工厂整理发布。转载请注明出处。