Resolve "LangChain ValidationError"
Quick answer
A LangChain ValidationError is a Pydantic error raised when an object is built with a missing field, an unexpected field, or the wrong type. The error is self-documenting: loc names the field, type names the problem (missing, extra, or a type error), and input shows what you passed. The most common structural cause is mixing Pydantic v1 and v2 — modern LangChain uses Pydantic v2, so import BaseModel from pydantic, not from a v1 shim, and keep your schemas on one version.
LangChain throws this and the traceback looks intimidating:
pydantic_core._pydantic_core.ValidationError: 1 validation error for ChatOpenAI
openai_api_key
Field required [type=missing, input_value={...}, input_type=dict]But there's good news buried in it: this error tells you exactly what's wrong.
A LangChain ValidationError is a Pydantic error — LangChain builds all its
objects (chains, tools, output schemas, model wrappers) with Pydantic, so when the
data doesn't fit the model, Pydantic raises. And Pydantic errors are
self-documenting once you know how to read them.
This guide teaches you to read the error in ten seconds, then fixes the handful of causes behind almost every one — with the biggest being a Pydantic v1 vs v2 mismatch that people don't even realize they've created.
Quick Answer
A LangChain ValidationError is a Pydantic error. Read its three parts:
loc (which field failed), type (missing, extra, or a type error), and
input (what you passed). Fix the field loc names. The most common
structural cause is mixing Pydantic v1 and v2 — modern LangChain uses v2, so
from pydantic import BaseModel, not a v1 shim, and keep all schemas on one
version.
TL;DR
- It's a Pydantic error — LangChain validates everything with Pydantic.
- Read
loc/type/input— they name the field, the problem, and your value. type=missing→ you left out a required field.extra_forbidden→ you passed an unknown kwarg.- Type/instance error → usually a Pydantic v1 ↔ v2 mix; align your imports.
- From
with_structured_output→ the model's JSON didn't match your schema. Did not find openai_api_key→ set the key; it's a missing-field error.
Read the Error First
Every Pydantic error has the same three parts, and each answers a question:
| Part | Answers | Example |
|---|---|---|
loc | Which field failed? | openai_api_key |
type | What kind of problem? | missing, extra_forbidden, string_type |
input | What did you actually pass? | None, "...", {...} |
Read them as a sentence: field openai_api_key, problem missing, you passed
None → "I didn't set the API key." That's the whole diagnosis. When there are
several errors, each one has its own loc/type/input — fix them one at a time.
Triage by Error Type
Step-by-step Solution
Cause 1: Missing required field (type=missing)
The loc names exactly what you forgot. Provide it:
from langchain_openai import ChatOpenAI
# ❌ no key → ValidationError: openai_api_key, Field required
llm = ChatOpenAI(model="gpt-4o")
# ✅ set it in the environment (OPENAI_API_KEY) or pass it explicitly
llm = ChatOpenAI(model="gpt-4o", api_key="sk-...")Did not find openai_api_key is the same thing — a missing field surfaced as a
friendlier message. Set OPENAI_API_KEY in your environment and it disappears.
For rate-limit issues once it is connected, see
fixing OpenAI RateLimitError.
Cause 2: Extra / unexpected field (extra_forbidden)
Many LangChain models forbid unknown kwargs, so a typo or a moved parameter raises:
# ❌ 'temperatur' typo, or a kwarg that belongs elsewhere
ChatOpenAI(model="gpt-4o", temperatur=0) # extra_forbidden
# ✅ correct name
ChatOpenAI(model="gpt-4o", temperature=0)Check the loc for the offending name. If you're passing provider-specific
options, route them through model_kwargs={...} rather than as top-level
arguments.
Cause 3: Pydantic v1 ↔ v2 mismatch (the big one)
This is the cause people never suspect. Modern LangChain (0.3+) is built on
Pydantic v2. If you define a schema with a v1 BaseModel — via
pydantic.v1 or the old langchain_core.pydantic_v1 shim — and hand it to a v2
LangChain API, validation fails with confusing messages like "Input should be a
valid dictionary or instance of X".
# ❌ mixing versions — v1 model into v2 LangChain
from langchain_core.pydantic_v1 import BaseModel # deprecated shim (v1)
class Person(BaseModel):
name: str
# ✅ use standard Pydantic v2 everywhere
from pydantic import BaseModel
class Person(BaseModel):
name: strPick one Pydantic version and stay there. With modern LangChain that's v2:
from pydantic import BaseModel. Don't import from pydantic.v1 or
langchain_core.pydantic_v1 unless you're pinned to an old LangChain — and if you
are, upgrade. Mixing versions is the root of most "impossible" ValidationErrors.
Confirm which Pydantic you're on:
import pydantic
print(pydantic.VERSION) # should be 2.x for modern LangChainCause 4: with_structured_output schema mismatch
When you ask a model for structured output, LangChain validates the JSON it
returns against your schema. If the model omits a field, returns the wrong type,
or sends null, you get a ValidationError — the model, not your code, produced
bad data.
from pydantic import BaseModel
from typing import Optional
class Profile(BaseModel):
name: str
age: Optional[int] = None # default makes it truly optional
llm_structured = llm.with_structured_output(Profile)
result = llm_structured.invoke("Extract the profile from: 'Alex, age unknown'")Fixes, in order of effort:
- Give optional fields a default (
= None).Optional[int]alone still errors on a missing value in Pydantic v2 — the default is what makes it optional. - Flatten nested schemas. Deeply nested models fail more often; weaker models especially struggle. A flat schema validates more reliably.
- Use a more capable model. Small/local models miss fields; a stronger model returns valid JSON more consistently.
- Retry the parse. Wrap with a retry or an
OutputFixingParserso a one-off bad response is repaired instead of crashing the run. - Try a different method. Some models do better with
with_structured_output(Schema, method="function_calling")than the default; test both.
The Optional trap: in Pydantic v2, Optional[int] means "can be None," not
"can be omitted." A field is only optional if it has a default. Write
age: Optional[int] = None. This single misunderstanding causes a large share of
structured-output ValidationErrors.
Reproduce and Debug
Print the raw error structure to see every failure at once — don't rely on the formatted string:
from pydantic import ValidationError
try:
Profile(name="Alex") # missing/invalid fields
except ValidationError as e:
for err in e.errors():
print(err["loc"], "→", err["type"], "→", err.get("input"))
# ('age',) → int_parsing → 'unknown' (example)e.errors() returns a list of dicts with loc, type, msg, and input — the
same three signals as the diagram, in code. This is the fastest way to debug a
schema that fails on real model output.
Verification Steps
- The object constructs without raising:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o") # no ValidationError
print(type(llm).__name__)pydantic.VERSIONis2.xand all your schemas import frompydantic.- A structured-output round-trip returns a valid object on a realistic input.
e.errors()is empty for the inputs you expect to succeed.- Missing-key errors are gone once
OPENAI_API_KEY(or the relevant key) is set.
Green state: objects construct cleanly, pydantic.VERSION is 2.x with no v1
imports anywhere, and with_structured_output returns a validated model on
representative inputs.
Prevention
- Standardize on Pydantic v2 imports (
from pydantic import BaseModel) project-wide. - Grep for
pydantic.v1andpydantic_v1and remove them. - Give every optional schema field an explicit default.
- Read
e.errors()when debugging — don't eyeball the formatted string. - Wrap structured output in a retry for production robustness.
- Set API keys via environment variables, checked at startup.
- Pin compatible
langchain,langchain-core, andpydanticversions together.
Troubleshooting Matrix
type in the error | Meaning | Fix |
|---|---|---|
missing | Required field not provided | Provide the field in loc |
extra_forbidden | Unknown kwarg passed | Remove it / use model_kwargs |
string_type / int_parsing | Wrong type for the field | Pass the correct type |
model_type / is_instance_of | v1 model into v2 API | Align Pydantic imports to v2 |
From with_structured_output | Model JSON ≠ schema | Defaults, flatten, retry, stronger model |
Did not find ..._api_key | API key not set | Set env var / pass api_key |
| Optional field still "required" | No default given | Add = None |
Related Guides
- Fix "Token indices sequence length is longer than the specified maximum"
- Fix OpenAI RateLimitError (429)
- Resolve ChromaDB collection does not exist
- Resolve OSError: Can't load tokenizer
- Building reliable structured output with LLMs
External References
- Pydantic — Validation errors
- LangChain — Pydantic compatibility
- LangChain — Structured outputs
- Pydantic — Migration guide (v1 to v2)
FAQs
Is ValidationError from LangChain or Pydantic?
From Pydantic. LangChain uses Pydantic models throughout, so the exception class
is Pydantic's. That's why the fix is always about the data or schema, not
LangChain internals.
How do I see all validation errors at once?
Catch the exception and call e.errors() — it returns a list, one dict per
failure with loc, type, msg, and input. The formatted string shows them
too, but e.errors() is easier to inspect programmatically.
Do I need to rewrite my v1 schemas for v2?
Usually only small changes: validator decorators (@field_validator), Config
becoming model_config, and defaults for optionals. The Pydantic migration guide
lists them. It's worth it — staying on v1 with modern LangChain invites these
errors.
Why does it work with one model but not another? Structured output depends on the model producing schema-valid JSON. A weaker or local model omits fields a stronger one includes. Same schema, different compliance — loosen the schema or use a stronger model.
Can I ignore validation and just take the raw output?
You can skip with_structured_output and parse the text yourself, but you lose
the guarantees. Better to fix the schema (defaults, flattening) or add a retry so
you keep validation and robustness.
Key takeaways
- •A LangChain ValidationError is a Pydantic error — read loc (the field), type (the problem), and input (what you sent).
- •'Field required' with type=missing means you left out a required argument named in loc.
- •The most common structural cause is mixing Pydantic v1 and v2; modern LangChain uses v2, so import from pydantic.
- •with_structured_output raises this when the model's JSON doesn't match your schema — add defaults, retry, or use a stronger model.
- •'Did not find openai_api_key' is a ValidationError too — set the API key in the environment or pass it explicitly.
- •Optional fields still error if your schema marks them required; give them a default of None.
Frequently asked questions
What causes a LangChain ValidationError?
LangChain builds its objects with Pydantic, so a ValidationError means the data didn't match the model. The common causes are a missing required field, an unexpected extra field, the wrong type, a Pydantic v1 vs v2 mismatch, or a structured-output call where the model's JSON didn't match your schema. The error's loc field names exactly what failed.
How do I read a Pydantic ValidationError in LangChain?
Each error has three parts. loc is the field path that failed. type is the category — missing, extra_forbidden, or a type error. input is the value you actually passed. Read them together: 'openai_api_key, Field required, type=missing' means you didn't provide the API key. Fix the field that loc names.
Why does with_structured_output raise a ValidationError?
Because the model returned JSON that doesn't satisfy your Pydantic schema — a missing field, a wrong type, or a null where a value is required. Make optional fields Optional with a default of None, simplify or flatten nested schemas, use a more capable model, or wrap the parse in a retry or OutputFixingParser.
How do I fix the Pydantic v1 vs v2 mismatch in LangChain?
Modern LangChain (0.3 and later) uses Pydantic v2. Define your schemas with from pydantic import BaseModel — not from pydantic.v1 or the old langchain_core.pydantic_v1 shim — and don't mix versions in one program. Mixing them produces errors like 'Input should be a valid dictionary or instance of X'.
Why do I get 'Did not find openai_api_key' as a ValidationError?
Because the model class validates the API key at construction time. Set OPENAI_API_KEY in your environment, or pass api_key=... explicitly to the constructor. It surfaces as a ValidationError with loc=openai_api_key and type=missing, which is really just 'the key isn't set'.
My field is Optional but still fails as required — why?
In Pydantic v2, Optional[str] alone does not make a field optional at validation; it only allows None. To make it truly optional, give it a default: field: Optional[str] = None. Without the default, a missing value still raises type=missing.
Software Engineering Leader & Technical Author · Updated July 24, 2026