LangChain Error Handling and Debugging
In Agent development, various errors are inevitable. This article sorts out common error types, debugging methods, and best practices.
Common Error Types
| Error Type | Typical Cause | Solution |
|---|---|---|
| ImportError | Provider package not installed | pip install langchain-deepseek, etc. |
| API Key Error | .env not configured or Key invalid | Check environment variables and Key validity |
| Timeout Error | Network issues or slow model response | Set the timeout parameter |
| Token Limit Exceeded | Message history is too long | Use trim_messages() to trim |
| Tool Call Error | Exception inside the tool | Use ToolException + handle_tool_errors |
| Model Return Format Error | Model output does not meet expectations | Use structured output + handle_errors |
ModelRetryMiddleware - Model Call Retry
LangChain provides built-in retry middleware:
Example
from langchain.agents.middleware import ModelRetryMiddleware
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
# Built-in model retry middleware
# Automatically retry when model call fails
agent = create_agent(
model=init_chat_model("deepseek:deepseek-v4-flash", timeout=30, max_retries=2),
middleware=[
ModelRetryMiddleware(
max_retries=3, # Retry up to 3 times
backoff_factor=2.0, # Backoff factor (2s, 4s, 8s)
)
],
system_prompt="You are EXAMPLE's assistant.",
)
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
# Built-in model retry middleware
# Automatically retry when model call fails
agent = create_agent(
model=init_chat_model("deepseek:deepseek-v4-flash", timeout=30, max_retries=2),
middleware=[
ModelRetryMiddleware(
max_retries=3, # Retry up to 3 times
backoff_factor=2.0, # Backoff factor (2s, 4s, 8s)
)
],
system_prompt="You are EXAMPLE's assistant.",
)
ToolRetryMiddleware - Tool Call Retry
Example
from langchain.agents.middleware import ToolRetryMiddleware
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[my_tool],
middleware=[
ToolRetryMiddleware(
max_retries=3,
backoff_factor=1.5,
)
],
)
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[my_tool],
middleware=[
ToolRetryMiddleware(
max_retries=3,
backoff_factor=1.5,
)
],
)
The built-in RetryMiddleware and custom @wrap_model_call / @wrap_tool_call can coexist. Put the built-in middleware at the front of the middleware list as the outermost protection.
debug=True - Detailed Logs
Example
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
# Enable debug mode to output detailed execution logs
agent = create_agent(
model=init_chat_model("deepseek:deepseek-v4-flash"),
debug=True, # Enable debug logging
system_prompt="You are EXAMPLE's assistant.",
)
# When executing, it will print:
# - Input state of each node
# - Output state of each node
# - Edge jump decisions
result = agent.invoke({
"messages": [HumanMessage(content="Hello")]
})
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
# Enable debug mode to output detailed execution logs
agent = create_agent(
model=init_chat_model("deepseek:deepseek-v4-flash"),
debug=True, # Enable debug logging
system_prompt="You are EXAMPLE's assistant.",
)
# When executing, it will print:
# - Input state of each node
# - Output state of each node
# - Edge jump decisions
result = agent.invoke({
"messages": [HumanMessage(content="Hello")]
})
Example output with debug=True:
[DEBUG] Starting graph execution
[DEBUG] Executing node: model
[DEBUG] Node 'model' input: {'messages': [HumanMessage(content='你好')]}
[DEBUG] Node 'model' output: {'messages': [AIMessage(content='你好!...')]}
[DEBUG] Edge 'model' -> '__end__': routing to __end__
[DEBUG] Graph execution complete
stream_mode="debug" - Most Detailed Debug Information
Example
# Get the most detailed information via stream_mode="debug"
for event in agent.stream(
{"messages": [HumanMessage(content="Hello")]},
stream_mode="debug",
):
# event contains: node name, input, output, timestamp, task info, etc.
print(f"[{event['type']}] {event.get('name', '')}")
if 'input' in event:
print(f" Input: {event['input']}")
if 'output' in event:
print(f" Output: {event['output']}")
for event in agent.stream(
{"messages": [HumanMessage(content="Hello")]},
stream_mode="debug",
):
# event contains: node name, input, output, timestamp, task info, etc.
print(f"[{event['type']}] {event.get('name', '')}")
if 'input' in event:
print(f" Input: {event['input']}")
if 'output' in event:
print(f" Output: {event['output']}")
Common Troubleshooting
Problem 1: The model keeps calling tools without stopping
Possible cause: The information returned by the tool is insufficient, and the model cannot determine whether the task is complete. Solutions:
- Make the tool return more explicit information (e.g., "Task completed")
- Set the stop condition in system_prompt
- Use after_model to check the loop count, and jump_to="end" after exceeding the threshold
Problem 2: The model called the wrong tool or parameters
Possible cause: The tool description is unclear. Solutions:
- Optimize the tool function's docstring
- Use args_schema to restrict parameter ranges
- Use a better model (e.g., deepseek-v4-pro instead of deepseek-v4-flash)
Problem 3: Conversation memory is not working
Checklist:
- Did you pass the checkpointer parameter?
- Did you use the same thread_id every time?
- If using SqliteSaver, does the database file exist and is it writable?