实现参考
生产故障诊断中心

LangChain v1 与 LangGraph 生产故障诊断中心:13 个真实报错对照

线上出了问题,最先需要的不是原理,而是一张能对上号的表:我看到的这行报错,最可能是什么原因,怎么确认,怎么改。 本页把 LangChain v1、create_agent 和 LangGraph 项目里最常见的 13 种失败逐个复现,所有报错原文都来自可重复运行的脚本,而不是凭记忆整理。

本页是查表用的参考页。每一行只给出诊断结论,原理和完整实验在链接的专题里。

适用版本与验证信息

项目内容
验证日期2026-10-25
Python3.12.12
包版本langchain==1.4.7、langchain-core==1.7.0、langgraph==1.2.17、langgraph-checkpoint==4.3.0
模型脚本化模型:按预设顺序回放固定的消息,不联网、不需要 API Key
官方来源LangChain v1 迁移指南 (opens in a new tab)、LangGraph 常见错误 (opens in a new tab),对照官方文档仓库 langchain-ai/docs (opens in a new tab) 提交 b8d4ced(2026-10-16)
实验代码站点仓库 labs/production-failure-index/,依赖锁定在 labs/requirements/v1.txt

报错文字会随版本变化。遇到与本页措辞不同的报错时,以你环境里的实际输出为准,用 python3 labs/run.py --lab production-failure-index 可以在自己的版本下重新生成本页的原始输出。

先说结论

13 个失败里,有 3 个根本不会抛异常,这是生产里最难排查的一类:

  • 模型漏掉必填参数(G)和调用不存在的工具(H):框架把错误变成 ToolMessage(status="error") 交还给模型,运行继续,只有看消息轨迹才发现;
  • 使用已弃用的 create_react_agent(D):只有一条弃用警告,代码照常运行。

和上面相反,工具内部抛出的异常(F)会让整个运行失败,不会被自动转换成给模型的错误消息。同样是“工具出了问题”,两种路径的表现完全不同,监控要分别覆盖。

处理顺序建议:先看异常类和第一行报错,在下面的对照表里定位;表里没有的,再用“消息轨迹 + 检查点历史”还原现场。

复现脚本

下面的脚本一次性触发全部 13 种情况,并打印异常类和第一行报错。它依赖的脚本化模型、工具定义在另一个实验的共享模块里,脚本开头已加入对应路径:

capture_errors.py
"""Trigger the failures an LCEL/LangGraph v1 project meets most often and print what they really look like.
 
Every case uses a scripted model, so the messages are identical on every run.
"""
import operator
import re
import sys
import warnings
from pathlib import Path
from typing import Annotated, TypedDict
 
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "agent-vs-langgraph"))
 
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langchain_core.messages import AIMessage
from langchain_core.tools import tool
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import END, START, StateGraph
from langgraph.types import Command
 
from shared import REFUNDS, ScriptedChatModel, lookup_order, refund
 
 
def first_line(text: str) -> str:
    line = (text.strip().splitlines() or [""])[0]
    return re.sub(r" \(/[^)]*\)", " (<path>)", line)[:230]  # drop machine-specific paths
 
 
def case(label: str, fn) -> None:
    print(label)
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        try:
            outcome = fn()
            print(f"    no exception{': ' + outcome if outcome else ''}")
        except BaseException as exc:  # noqa: BLE001 - the point is to show any failure
            print(f"    {type(exc).__name__}: {first_line(str(exc))}")
        for w in caught:
            print(f"    warning {w.category.__name__}: {first_line(str(w.message))}")
 
 
def model(*messages: AIMessage) -> ScriptedChatModel:
    return ScriptedChatModel(script=list(messages))
 
 
def tool_call(name: str, args: dict, call_id: str = "c1") -> AIMessage:
    return AIMessage(content="", tool_calls=[{"name": name, "args": args, "id": call_id}])
 
 
# --- migration errors -------------------------------------------------------
case("A. create_agent(prompt=...)", lambda: create_agent(model(AIMessage(content="x")), tools=[lookup_order], prompt="hi"))
case("B. from langchain.agents import AgentExecutor", lambda: exec("from langchain.agents import AgentExecutor"))
case("C. from langchain.chains import LLMChain", lambda: exec("from langchain.chains import LLMChain"))
case(
    "D. from langgraph.prebuilt import create_react_agent",
    lambda: exec("from langgraph.prebuilt import create_react_agent; create_react_agent(model(AIMessage(content='x')), [lookup_order])"),
)
 
 
# --- agent loop and tools ---------------------------------------------------
def recursion_limit():
    looping = model(*[tool_call("lookup_order", {"order_id": "A1"}, f"c{i}") for i in range(10)])
    create_agent(looping, tools=[lookup_order]).invoke({"messages": [("user", "go")]}, {"recursion_limit": 3})
 
 
@tool
def db_lookup(key: str) -> str:
    """Look up a key (always fails)."""
    raise RuntimeError("database unavailable")
 
 
def tool_raises():
    scripted = model(tool_call("db_lookup", {"key": "a"}), AIMessage(content="done"))
    create_agent(scripted, tools=[db_lookup]).invoke({"messages": [("user", "go")]})
 
 
def tool_message(scripted: ScriptedChatModel) -> str:
    result = create_agent(scripted, tools=[lookup_order]).invoke({"messages": [("user", "go")]})
    tool_msg = next(m for m in result["messages"] if m.type == "tool")
    return f"ToolMessage(status={tool_msg.status}): {' '.join(tool_msg.content.split())}"
 
 
case("E. recursion_limit too small for the loop", recursion_limit)
case("F. a tool raises RuntimeError", tool_raises)
case("G. the model omits a required tool argument", lambda: tool_message(model(tool_call("lookup_order", {}), AIMessage(content="done"))))
case("H. the model calls a tool that does not exist", lambda: tool_message(model(tool_call("no_such_tool", {}), AIMessage(content="done"))))
 
 
# --- graph and checkpoint errors --------------------------------------------
class Shared(TypedDict, total=False):
    facts: list  # no reducer on purpose
 
 
def parallel_write():
    builder = StateGraph(Shared)
    builder.add_node("a", lambda state: {"facts": ["a"]})
    builder.add_node("b", lambda state: {"facts": ["b"]})
    builder.add_edge(START, "a")
    builder.add_edge(START, "b")
    builder.add_edge("a", END)
    builder.add_edge("b", END)
    builder.compile().invoke({})
 
 
def simple_graph(checkpointer=None):
    builder = StateGraph(Shared)
    builder.add_node("a", lambda state: {"facts": ["a"]})
    builder.add_edge(START, "a")
    builder.add_edge("a", END)
    return builder.compile(checkpointer=checkpointer)
 
 
def hitl_agent(checkpointer=None):
    scripted = model(tool_call("refund", {"order_id": "A1", "amount": 9.0}), AIMessage(content="done"))
    middleware = [HumanInTheLoopMiddleware(interrupt_on={"refund": True})]
    return create_agent(scripted, tools=[refund], middleware=middleware, checkpointer=checkpointer)
 
 
def resume_without_checkpointer():
    agent = hitl_agent()
    config = {"configurable": {"thread_id": "t"}}
    agent.invoke({"messages": [("user", "refund")]}, config)
    agent.invoke(Command(resume={"decisions": [{"type": "approve"}]}), config)
 
 
case("I. two parallel nodes write one key without a reducer", parallel_write)
case("J. get_state on a graph compiled without a checkpointer", lambda: simple_graph().get_state({"configurable": {"thread_id": "t"}}))
case("K. checkpointer present but no thread_id", lambda: simple_graph(InMemorySaver()).invoke({}))
case("L. resume a human-in-the-loop run without a checkpointer", resume_without_checkpointer)
case("M. resume on a thread that has no saved run", lambda: simple_graph(InMemorySaver()).invoke(None, {"configurable": {"thread_id": "new"}}))

脚本的实际输出,也是下面对照表里所有“报错原文”的来源:

A. create_agent(prompt=...)
    TypeError: create_agent() got an unexpected keyword argument 'prompt'
B. from langchain.agents import AgentExecutor
    ImportError: cannot import name 'AgentExecutor' from 'langchain.agents' (<path>)
C. from langchain.chains import LLMChain
    ModuleNotFoundError: No module named 'langchain.chains'
D. from langgraph.prebuilt import create_react_agent
    no exception
    warning LangGraphDeprecatedSinceV10: create_react_agent has been moved to `langchain.agents`. Please update your import to `from langchain.agents import create_agent`. Deprecated in LangGraph V1.0 to be removed in V2.0.
E. recursion_limit too small for the loop
    GraphRecursionError: Recursion limit of 3 reached without hitting a stop condition. You can increase the limit by setting the `recursion_limit` config key.
F. a tool raises RuntimeError
    RuntimeError: database unavailable
G. the model omits a required tool argument
    no exception: ToolMessage(status=error): Error invoking tool 'lookup_order' with kwargs {} with error: order_id: Field required Please fix the error and try again.
H. the model calls a tool that does not exist
    no exception: ToolMessage(status=error): Error: no_such_tool is not a valid tool, try one of [lookup_order].
I. two parallel nodes write one key without a reducer
    InvalidUpdateError: At key 'facts': Can receive only one value per step. Use an Annotated key to handle multiple values.
J. get_state on a graph compiled without a checkpointer
    ValueError: No checkpointer set
K. checkpointer present but no thread_id
    ValueError: Checkpointer requires one or more of the following 'configurable' keys: thread_id, checkpoint_ns, checkpoint_id
L. resume a human-in-the-loop run without a checkpointer
    RuntimeError: Cannot use Command(resume=...) without checkpointer
M. resume on a thread that has no saved run
    EmptyInputError: Received no input for __start__

排障对照表

迁移相关(A–D)

编号报错原文原因验证处理
ATypeError: create_agent() got an unexpected keyword argument 'prompt'从 create_react_agent 迁移时,prompt= 在 create_agent 里改名为 system_prompt=对照官方迁移指南的参数表改参数名,详见迁移 Runbook
BImportError: cannot import name 'AgentExecutor' from 'langchain.agents'v1 精简了 langchain 命名空间,旧的 AgentExecutor 不在这里查导入兼容矩阵安装 langchain-classic 并改用 langchain_classic.agents.AgentExecutor,或迁到 create_agent
CModuleNotFoundError: No module named 'langchain.chains'chains 整个模块已不在 langchain 里同上同上:新位置是 langchain_classic.chains,旧路径不会恢复;旧链改写成 LCEL 见RetrievalQA 与 LLMChain 迁移到 LCEL
D无异常;LangGraphDeprecatedSinceV10: create_react_agent has been moved to langchain.agents ...create_react_agent 已弃用,计划在 LangGraph V2.0 移除运行时开启警告显示(python -W default)改用 from langchain.agents import create_agent,参数差异见迁移 Runbook

Agent 循环与工具(E–H)

编号报错原文原因验证处理
EGraphRecursionError: Recursion limit of 3 reached without hitting a stop condition ...循环步数超过 recursion_limit看消息轨迹里工具调用了几轮按“N 轮工具调用需要至少 2N+2”估算上限,详见迁移 Runbook;加了中间件后每一轮还会多占步数,见Agent 中间件与安全护栏
FRuntimeError: database unavailable(工具内部抛出的原始异常)工具执行时抛出异常,没有被转换成给模型的消息,整个运行失败在工具内部加日志,或捕获 invoke 的异常工具内部自己处理可恢复的错误,返回描述性字符串;不可恢复的才抛出;想把异常交还给模型,见工具调用 schema 排障
G无异常;ToolMessage(status=error):Error invoking tool 'lookup_order' with kwargs {} with error: order_id: Field required ...模型生成的参数不满足工具的参数模式,框架把校验错误反馈给了模型打印消息轨迹,找 status="error" 的 ToolMessage检查工具的描述和参数说明是否清晰(参数说明的来源见工具调用 schema 排障);对重要工具统计这类消息的比例并告警
H无异常;ToolMessage(status=error):Error: no_such_tool is not a valid tool, try one of [lookup_order].模型调用了没有注册的工具名同上检查工具列表是否和提示里描述的一致;统计并告警

图与状态(I)

编号报错原文原因验证处理
IInvalidUpdateError: At key 'facts': Can receive only one value per step. Use an Annotated key to handle multiple values.两个并行节点写同一个状态键,该键没有 reducer看报错里的键名,检查状态定义给该键声明带 reducer 的类型,详见 create_agent 还是 LangGraph?

checkpoint 与恢复(J–M)

编号报错原文原因验证处理
JValueError: No checkpointer set编译图时没有传 checkpointer,却调用了 get_state 等需要它的接口graph.checkpointer 是否为 Nonecompile(checkpointer=...),详见 checkpoint 与故障恢复
KValueError: Checkpointer requires one or more of the following 'configurable' keys: thread_id, checkpoint_ns, checkpoint_id有 checkpointer,但调用时没有传 thread_id检查 config["configurable"]每次调用都带 thread_id,详见 checkpoint 与故障恢复;从旧对话记忆迁移时的这个坑见ConversationBufferMemory 迁移到 v1
LRuntimeError: Cannot use Command(resume=...) without checkpointer人工审批中断后要恢复,但 Agent 没有配 checkpointer;第一次调用不会报错,恢复时才暴露先看第一次调用的结果里是否有 __interrupt__创建 Agent 时传入 checkpointer,详见 create_agent 还是 LangGraph?
MEmptyInputError: Received no input for __start__用 invoke(None, config) 恢复,但这个 thread_id 下没有已保存的运行检查恢复用的 thread_id 是否与崩溃时一致沿用原来的 thread_id,详见 checkpoint 与故障恢复

模型服务相关

下面这些错误来自本站对本地模拟的 OpenAI 兼容服务的验收实验,错误类名是 langchain-openai 的真实类名,错误内容是模拟服务返回的文本,不代表任何真实服务商:

现象原因处理
Agent 返回空内容且没有调用任何工具,不抛异常模型返回的工具参数不是合法 JSON,被放进 invalid_tool_calls验收时断言 invalid_tool_calls 为空,线上监控空回复,详见OpenAI 兼容模型接入验收
OpenAIInvalidRequestError(继承 openai.BadRequestError)服务端不支持你传的参数,例如 tools 或 response_format同上
OpenAITimeoutError / OpenAIRateLimitError超时或限流;默认会自动重试,请求数会被放大同上

失败与回滚

  • 找不到对应的报错:从 invoke 的结果里取出完整消息轨迹,以及(有 checkpointer 时)get_state_history 的检查点历史,逐步对照预期。多数问题在轨迹里能直接看出是哪一步偏离;
  • 把线上问题变成回归测试:对每个修复过的问题,写一个与本页 capture_errors.py 同样形态的脚本,用脚本化模型复现,并把期望输出纳入版本控制。下次升级依赖时,输出变化就是一次明确的提示;
  • 升级前后对比:升级 langchain 或 langgraph 之前,先在隔离环境跑一遍本页脚本,把输出差异当作变更清单。

相关阅读

来源

以上来源均于 2026-10-25 核对。表中“报错原文”全部来自站点仓库 labs/production-failure-index/ 在上表版本下的实际运行。

维护信息

  • 编辑:LangChain 中文网编辑部(内容标准见编辑与纠错说明);
  • 最近验证:2026-10-25;
  • 复现:先执行 labs/setup-envs.sh v1 重建环境,再执行 python3 labs/run.py --lab production-failure-index;
  • 发现错误请按联系我们反馈。