n4nAI

Common LangChain error messages and what they mean

Decode the most common LangChain error messages, from authentication failures to output parsing issues, and learn actionable fixes for production.

n4n Team4 min read985 words

Audio narration

Coming soon — every post will get a voice note here.

Every engineer who has shipped a LangChain app has stared at a cryptic stack trace. The common langchain error messages usually fall into a handful of categories: misconfigured credentials, broken model bindings, malformed prompts, and output parsing mismatches. This guide walks through the ones you’ll hit first and gives an ordered path to fix them without guesswork.

LangChain versions matter. The examples below target langchain 0.1.x and openai 1.x. Error classes moved from openai.error to top-level openai exceptions in the 1.0 SDK, so the same root cause now raises a different type than it did a year ago.

1. Authentication and API key errors

The first wall you hit is almost always credentials. LangChain does not invent its own auth layer; it passes keys to the underlying SDK. If OPENAI_API_KEY is missing, ChatOpenAI() raises a ValueError before any network call:

from langchain.chat_models import ChatOpenAI

# Raises: ValueError: You must pass an openai_api_key or set OPENAI_API_KEY env var.
llm = ChatOpenAI()

The fix is boring but strict: load from environment, never hardcode. Use python-dotenv and fail fast at startup.

import os
from dotenv import load_dotenv

load_dotenv()
assert os.getenv("OPENAI_API_KEY"), "OPENAI_API_KEY not set"

If you see openai.AuthenticationError instead of ValueError, you are on openai>=1.0 and LangChain forwarded the SDK error. The remedy is identical.

A subtler pitfall is using the wrong class for the provider. OpenAI (completions) vs ChatOpenAI (chat) both read the same env var but send different request shapes. If you swap them, you get InvalidRequestError about model compatibility, not an auth error. Keep your imports explicit and pin langchain and openai versions together in your lockfile.

2. Model not found or unsupported parameters

After auth, the next tier of common langchain error messages comes from model routing. A typo in model_name surfaces as NotFoundError or InvalidRequestError:

llm = ChatOpenAI(model_name="gpt-4-turbo-preview")  # fine
llm = ChatOpenAI(model_name="gpt-4-trubo")          # InvalidRequestError: model does not exist

With Azure OpenAI, the parameter is deployment_name, not model_name. Using the wrong one yields a 404 that LangChain wraps as ValueError: Unable to infer model name. Read the provider docs; don’t assume the OpenAI signature transfers.

Parameter validation also bites. temperature=2.0 is out of range for most models. Pydantic in LangChain will raise ValidationError at construction:

ChatOpenAI(temperature=2.0)  # ValidationError: ensure this value is less than or equal to 1.0

Passing arbitrary model_kwargs can trigger a provider-side reject. This works:

ChatOpenAI(model_kwargs={"top_p": 0.9})

But {"frequency_penalty": "high"} raises InvalidRequestError because the type is wrong. Tradeoff: strict validation catches bugs early but blocks dynamic config from env vars. If you load parameters from a string, cast and clamp before passing.

3. Rate limits and provider degradation

Once the code runs, throughput exposes the next class of common langchain error messages: RateLimitError and APIConnectionError. In a dev loop, a forgotten for over 100 prompts will trip the 60k TPM limit fast.

from openai import RateLimitError
from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI(max_retries=3, request_timeout=30)

try:
    llm.invoke("Summarize this")
except RateLimitError as e:
    # log, backoff, or degrade
    print(f"Rate limited: {e.status_code}")

The max_retries uses exponential backoff from the OpenAI SDK. But retries are not infinite. If you route through a gateway such as n4n.ai, automatic fallback when a provider is rate-limited or degraded can mask these errors, but your code should still catch RateLimitError to log and shed load.

APIConnectionError often points to a proxy or DNS issue, not the model. Set request_timeout explicitly; the default can hang in constrained networks. Pitfall: catching Exception broadly hides the root cause. Catch the specific SDK error and let unknown ones propagate.

4. Prompt template and input validation errors

Prompt construction fails loudly when variables mismatch. PromptTemplate.from_template infers input_variables from {braces}. Call .format() with the wrong keys and you get a KeyError:

from langchain.prompts import PromptTemplate

prompt = PromptTemplate.from_template("Write a {style} poem about {topic}")
prompt.format(topic="rust")  # KeyError: 'style'

The fix is to declare variables explicitly and validate at build time:

prompt = PromptTemplate(input_variables=["style", "topic"], template="Write a {style} poem about {topic}")

A common tradeoff: loose templates with .from_template are faster to write but blow up at runtime. Explicit input_variables shift the check to import time. In a large app, I prefer the latter.

Escaping braces is another silent killer. If your prompt contains literal { for JSON schema, double them: {{"key": "value"}}. Forgetting this raises KeyError on the inner quotes. With FewShotPromptTemplate, mismatched example keys vs input_variables raise ValueError at construction—catch it in tests.

5. Output parser exceptions

The most frustrating of the common langchain error messages is OutputParserException. You asked for JSON, the model returned prose. With PydanticOutputParser, a missing field raises:

from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel

class Answer(BaseModel):
    score: int
    rationale: str

parser = PydanticOutputParser(pydantic_object=Answer)
# If LLM output is "Score: 5, Reason: good", parser.parse throws OutputParserException

Two fixes. First, always inject parser.get_format_instructions() into the prompt. Second, use OutputFixingParser to ask the model to repair its own output:

from langchain.output_parsers import OutputFixingParser

fixing_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI())
result = fixing_parser.parse(bad_output)

Cost tradeoff: the fix step is an extra LLM call. In high-volume pipelines, strict parsing with a cheap retry is better than a fix call per failure. For CommaSeparatedListOutputParser, a single stray comma breaks splitting—preprocess the raw text or use EnumOutputParser when the domain is closed.

6. Retriever and vector store errors

RAG chains fail at the data layer. Chroma without a persistence dir loses collections on exit, then get_retriever() returns empty results silently. Explicit init avoids it:

from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

vectordb = Chroma(persist_directory="./db", embedding_function=OpenAIEmbeddings())
retriever = vectordb.as_retriever(search_kwargs={"k": 3})

Dimension mismatch between embeddings and store raises ValueError: shape mismatch. If you switch from text-embedding-ada-002 to a local model, rebuild the index. There is no in-place migration.

With hosted stores like Pinecone, IndexNotFoundError means the index name is wrong or region mismatched. A Document missing page_content raises ValueError during upsert—validate your loaders before they hit the store.

7. Async and event loop pitfalls

Mix sync and async and you meet RuntimeError: Event loop is closed. LangChain’s ainvoke must run inside a live loop:

import asyncio
from langchain.chains import LLMChain

async def run(chain, q):
    return await chain.ainvoke({"query": q})

asyncio.run(run(chain, "hi"))  # correct

In Jupyter, the loop already exists; in a script it doesn’t. Don’t call asyncio.get_event_loop() blindly—use asyncio.run. If you are already inside a running loop (FastAPI, asyncio server), calling asyncio.run raises RuntimeError: cannot be called from a running event loop. Use await directly.

Tradeoff: sync invoke is simpler but blocks the worker. For Flask/Django, wrap async in a thread or use the sync API. asyncio.TimeoutError from a chain usually means a slow provider, not a code bug—set per-call timeouts.

8. Debugging strategy: verbose, tracing, isolation

When the above don’t explain it, turn on LangChain’s debug flag:

import langchain
langchain.debug = True

This prints every prompt, response, and intermediate step. Beware: it logs full payloads, including keys if you embed them. For production, use LangSmith or OpenLLMetry instead of debug=True.

Ordered path when a new error appears:

  1. Reproduce with a direct ChatOpenAI().invoke() call—bypass chains.
  2. If that fails, it’s auth/model/rate limit (sections 1–3).
  3. If direct call works, add langchain.debug and inspect the prompt sent by the chain.
  4. If prompt is wrong, fix template (section 4).
  5. If response is wrong shape, fix parser (section 5).
  6. If retriever returns nothing, check vector store (section 6).
  7. If stack mentions await or loop, fix async boundary (section 7).

This sequence cuts debug time from hours to minutes. The common langchain error messages are rarely mysterious once you isolate the layer. Write a tiny script that exercises each component alone; the monolith chain is the last place you should look.

Tagslangchainerror-codesdebuggingguide

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All langchain debugging & observability posts →