langchain-common-errors

Paste-match catalog of 14 real LangChain 1.0 / LangGraph 1.0 exceptions with named causes and named fixes, plus a triage decision tree. Use when you have a traceback and want the specific fix, not speculative documentation. Covers ImportError (0.2/0.3 → 1.0 migration), AttributeError on AIMessage.content, KeyError in LCEL and prompts, GraphRecursionError, silent thread_id memory loss, JSON-serialization crashes, and graphs that halt without reaching END. Trigger with "langchain error", "langgraph traceback", "OutputParserException", "GraphRecursionError", "ImportError langchain", "AttributeError AIMessage content".

claude-codecodex
2 Tools
langchain-py-pack Plugin
saas packs Category

Allowed Tools

ReadGrep

Provided by Plugin

langchain-py-pack

Claude Code skill pack for LangChain 1.0 + LangGraph 1.0 (Python) - 34 skills covering chains, agents, RAG, middleware, checkpointing, HITL, streaming, and production patterns

saas packs v2.0.0
View Plugin

Installation

This skill is included in the langchain-py-pack plugin:

/plugin install langchain-py-pack@claude-code-plugins-plus

Click to copy

Instructions

LangChain Common Errors (Python)

Overview

The same twelve-plus LangChain 1.0 / LangGraph 1.0 tracebacks show up every week

in production: ImportError: cannot import name 'ChatOpenAI' from 'langchain.chat_models',

AttributeError: 'list' object has no attribute 'lower', `GraphRecursionError:

Recursion limit of 25 reached, TypeError: Object of type datetime is not JSON

serializable, KeyError: 'question'` deep in LCEL internals. Stack traces are

ambiguous, docs sprawl across 0.2 / 0.3 / 1.0 eras, and engineers lose

30–90 minutes per incident re-deriving the fix.

This skill is a paste-match catalog of 14 entries (E01–E14) grouped into

3 reference files by category, plus a triage decision tree. Every entry opens

with the exact exception class and message string you see in your terminal,

names the cause in one sentence with a pain-catalog code, and gives a one-line

fix or a reference-file pointer. Pinned to langchain-core 1.0.x,

langchain 1.0.x, langgraph 1.0.x, verified 2026-04-21.

Pain-catalog anchors: P02, P06, P09, P10, P16, P17, P38, P39, P40, P41, P42, P55, P56, P57, P66.

Prerequisites

  • Python 3.10+
  • A traceback or a reproducible bug — this skill is diagnostic, not preventive
  • langchain-core >= 1.0, < 2.0, langgraph >= 1.0, < 2.0, and any provider

integration packages pinned to 1.0.x

  • anthropic >= 0.42 when using langchain-anthropic 1.0 (see E06)

Instructions

  1. Triage first. Read the first line of the traceback. Look up the exception

class in the catalog below or in Triage Decision Tree.

  1. Match the message string, not the call site. Each catalog entry opens with

the literal message pattern you see.

  1. Apply the named fix. If the entry points to a reference file, read that

file for the deep walk-through including codemods, before/after code, and

adjacent traps. Otherwise use the one-line fix here.

  1. Verify with a test. Every catalog entry names a test that will catch the

error in CI next time.

  1. If no match: check docs/pain-catalog.md for the exception class name or

a message substring. Do not add speculative fixes here without catalog evidence.

Catalog

Each entry is indexed as E## — ClassName: "message pattern" with a one-line

cause (pain-catalog code) and a one-line fix or reference pointer.

Category A — Import & migration errors (0.2 / 0.3 → 1.0)

Full detail, before/after code, codemod commands: import-migration.md.

E01 — ImportError: cannot import name 'ChatOpenAI' from 'langchain.chat_models'

  • Cause: Top-level langchain.chat_models / langchain.llms re-exports removed in 1.0 (P38).
  • Fix: from langchainopenai import ChatOpenAI. Run python -m langchaincli migrate for automated rewrites. See E01 in import-migration.md.

E02 — AttributeError: module 'langchain' has no attribute 'LLMChain'

  • Cause: Legacy chain classes (LLMChain, SequentialChain, TransformChain) removed in 1.0 in favor of LCEL (P39).
  • Fix: chain = prompt | llm | StrOutputParser(); .run(x) becomes .invoke({"input": x}). See E02 in import-migration.md.

E03 — ImportError: cannot import name 'ConversationBufferMemory'

  • Cause: All legacy memory classes removed in 1.0; LangGraph checkpointing is the replacement (P40).
  • Fix: Use InMemorySaver / PostgresSaver + threadid via LangGraph createreact_agent. See E03 in import-migration.md.

E04 — ImportError: cannot import name 'initialize_agent'

  • Cause: Legacy agent factories (initializeagent, AgentType, createopenaifunctionsagent) removed in 1.0 (P41).
  • Fix: from langgraph.prebuilt import createreactagent; createreactagent(model=llm, tools=tools, checkpointer=InMemorySaver()). See E04 in import-migration.md.

E05 — AttributeError: 'AgentAction' object has no attribute 'tool_name' (or inverse)

  • Cause: Legacy AgentAction / AgentFinish shape replaced by ToolCall objects; fields renamed .tool.toolname, .toolinput.args (P42).
  • Fix: Access toolcall["name"] / toolcall["args"] on message .toolcalls, not result["intermediatesteps"]. See E05 in import-migration.md.

E06 — KeyError: 'input' inside tool_use block parsing

  • Cause: langchain-anthropic >= 1.0 requires anthropic >= 0.40; SDK tool-use schema changed (P66).
  • Fix: pip install "langchain-anthropic>=1.0,<2.0" "anthropic>=0.42,<1.0" in the same commit. See E06 in import-migration.md.

Category B — Content-shape & prompt-template errors

Full detail, block-iterator extractor, jinja2 escape pattern: content-shape.md.

E07 — AttributeError: 'list' object has no attribute 'lower' (or .strip, .split, .format)

  • Cause: AIMessage.content is list[dict] on Claude with any non-text block and on OpenAI once tools are bound (P02).
  • Fix: Use msg.text() (LangChain 1.0+) or iterate and filter block["type"] == "text". See E07 in content-shape.md.

E08 — KeyError: '' inside runnables/passthrough.py or runnables/base.py

  • Cause: LCEL dict-shape mismatch between runnable stages; error surfaces at the consumer, not the producer (P06).
  • Fix: Insert RunnableLambda debug probes between stages and enable set_debug(True). See E08 in content-shape.md.

E09 — KeyError: '' inside prompts/chat.py or prompts/prompt.py on user input

  • Cause: ChatPromptTemplate.from_messages defaults to f-string parsing; user-provided { / } characters are parsed as template variables (P57).
  • Fix: Use MessagesPlaceholder("history") for variable content, or template_format="jinja2" for free-text templates, or escape literals as {{ / }}. See E09 in content-shape.md.

Category C — Agent & graph execution traps

Full detail, diagnostic callbacks, thread_id middleware, router asserts: graph-traps.md.

E10 — GraphRecursionError: Recursion limit of 25 reached without hitting a stop condition

  • Cause: createreactagent and StateGraph.compile() default recursion_limit=25 counts supersteps, not loop iterations; vague prompts never converge (P10, P55).
  • Fix: Set recursion_limit=10 for interactive use; add terminal edge on repeated tool-call names. See E10 in graph-traps.md.

E11 — AgentExecutor returns "I couldn't find the answer" on every tool call, no exception

  • Cause: handleparsingerrors=True catches tool exceptions and passes str(exc) (often empty) as observation; loop continues without signal (P09).
  • Fix: returnintermediatesteps=True, handleparsingerrors=False or migrate to LangGraph createreactagent. See E11 in graph-traps.md.

E12 — Multi-turn chat forgets everything between calls, no exception

  • Cause: LangGraph checkpointers key state by config["configurable"]["threadid"]; omitted threadid means every invocation gets a fresh state with no warning (P16).
  • Fix: Require thread_id at app boundary; wrap in middleware that raises on missing key. See E12 in graph-traps.md.

E13 — TypeError: Object of type is not JSON serializable

  • Cause: InMemorySaver / PostgresSaver / SqliteSaver serialize state as JSON on every superstep; non-primitives break at interrupt or checkpoint boundary (P17).
  • Fix: Keep state JSON-primitive only (str/int/float/bool/list/dict); serialize at node boundaries; or use JsonPlusSerializer for Pydantic v2. See E13 in graph-traps.md.

E14 — Graph halts without reaching END, no exception, no log

  • Cause: addconditionaledges(node, router, pathmap) where router returns a string not in pathmap causes silent termination on some 1.0 versions (P56).
  • Fix: assert routerreturn in pathmap; always include END explicitly; inspect graph.get_state(cfg).next. See E14 in graph-traps.md.

Output

  • Named cause tied to a P## pain-catalog code for every traceback
  • Named fix (one-line or a reference-file walk-through) tied to E## catalog entry
  • A regression test pattern that catches the error in CI next time
  • Triage path recorded for the incident retro (which entry matched, how long it took)

Error Handling

This skill is the error-handling reference for the pack. The triage workflow:

  1. First line of traceback → pick category in the table below.
  2. Exception class + message substring → pick E## entry above.
  3. Reference file → read the deep walk-through for before/after code and tests.
First-line pattern Category Entries Reference
ImportError from langchain.* A E01, E03, E04 import-migration.md
AttributeError on langchain.* module A E02 import-migration.md
AttributeError on AgentAction / ToolCall A E05 import-migration.md
ImportError / KeyError against langchain-anthropic A E06 import-migration.md
AttributeError on list.lower / .strip B E07 content-shape.md
KeyError in runnables/ B E08 content-shape.md
KeyError in prompts/ B E09 content-shape.md
GraphRecursionError C E10 graph-traps.md
Silent wrong answers / empty tool errors C E11 graph-traps.md
Multi-turn memory loss, no exception C E12 graph-traps.md
TypeError ... not JSON serializable C E13 graph-traps.md
Graph halts without reaching END C E14 graph-traps.md

For tracebacks that do not match: consult triage-decision-tree.md

for the full routing flowchart, then docs/pain-catalog.md for any remaining

pain codes. Escalate to the main thread before adding speculative fixes.

Examples

Example 1 — ImportError on a 0.3 → 1.0 upgrade

Incoming traceback:


Traceback (most recent call last):
  File "app.py", line 3, in <module>
    from langchain.chat_models import ChatOpenAI
ImportError: cannot import name 'ChatOpenAI' from 'langchain.chat_models'

Triage:

  1. First line is ImportError from langchain.chat_models → Category A.
  2. Matches E01 exactly.
  3. Cause: top-level re-exports removed in 1.0 (P38).
  4. Fix: rewrite imports and bump provider packages.

pip install "langchain-openai>=1.0,<2.0" "langchain-anthropic>=1.0,<2.0" "langchain-cli>=0.1"
python -m langchain_cli migrate src/

# Before
from langchain.chat_models import ChatOpenAI

# After
from langchain_openai import ChatOpenAI

Re-run tests. Next failure is almost always E07 (AIMessage.content shape)

once the imports resolve — walk that one next from content-shape.md.

Example 2 — GraphRecursionError triage

Incoming traceback:


Traceback (most recent call last):
  File "worker.py", line 88, in run
    result = agent.invoke({"messages": [("user", q)]}, config=cfg)
  ...
langgraph.errors.GraphRecursionError: Recursion limit of 25 reached without hitting a stop condition. You can increase the limit by setting the `recursion_limit` config key.

Triage:

  1. Exception class is GraphRecursionError → Category C.
  2. Matches E10 exactly.
  3. Cause: vague prompt or tool loop; default recursion_limit=25 (P10, P55).
  4. Before raising the limit, diagnose first — attach a StepLogger callback

(see graph-traps.md § E10) and count

real steps. If the same two node names alternate, it is a convergence bug,

not a budget bug.

Fix (budget only):


cfg = {"configurable": {"thread_id": tid}, "recursion_limit": 10}
agent.invoke(inp, config=cfg)

Fix (convergence + budget):


def _should_stop(state):
    recent = [m for m in state["messages"][-6:] if getattr(m, "tool_calls", None)]
    if len(recent) >= 3 and all(
        r.tool_calls[0]["name"] == recent[0].tool_calls[0]["name"] for r in recent
    ):
        return "end"
    return "continue"

graph.add_conditional_edges("agent", _should_stop, {"continue": "agent", "end": END})

Pair with a per-session token-budget middleware from langchain-cost-tuning.

Resources

  • Pack pain catalog: docs/pain-catalog.md — canonical entries for

P02, P06, P09, P10, P16, P17, P38, P39, P40, P41, P42, P55, P56, P57, P66

Ready to use langchain-py-pack?