InterviewsVector

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

How to read a Pydantic ValidationError: loc names the field, type names the problem, input shows what you sentA LangChain ValidationError is self-documenting. The loc line names the field that failed, the type says what kind of problem it is such as missing or extra, and the input value shows what you actually passed. Read these three parts and the fix is usually obvious.pydantic ValidationError1 validation error for ChatOpenAIopenai_api_keyField required[type=missing,input_value=None]loc → which field failedtype → what kind of probleminput → the value you passed
How to read a Pydantic ValidationError: loc names the field, type names the problem, input shows what you sent

Every Pydantic error has the same three parts, and each answers a question:

PartAnswersExample
locWhich field failed?openai_api_key
typeWhat kind of problem?missing, extra_forbidden, string_type
inputWhat 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

LangChain ValidationError causes, keyed on the error type: missing, extra, wrong type, or structured-output mismatchRead the type field and branch. A missing type means you left out a required field named in loc. Extra fields means an unknown keyword argument. A wrong type or instance error usually means a Pydantic v1 and v2 mismatch. A failure from with_structured_output means the model output did not match the schema.LangChain ValidationErrorRead error['type'] (and 'loc')type=missingProvide the fieldnamed in 'loc'extra fieldsRemove the kwarg,or allow extrawrong typePydantic v1 ↔ v2 —align your importstructured outputLoosen / retry /stronger model
LangChain ValidationError causes, keyed on the error type: missing, extra, wrong type, or structured-output mismatch

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: str
⚠️

Pick 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 LangChain

Cause 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 OutputFixingParser so 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

  1. The object constructs without raising:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o")   # no ValidationError
print(type(llm).__name__)
  1. pydantic.VERSION is 2.x and all your schemas import from pydantic.
  2. A structured-output round-trip returns a valid object on a realistic input.
  3. e.errors() is empty for the inputs you expect to succeed.
  4. 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.v1 and pydantic_v1 and 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, and pydantic versions together.

Troubleshooting Matrix

type in the errorMeaningFix
missingRequired field not providedProvide the field in loc
extra_forbiddenUnknown kwarg passedRemove it / use model_kwargs
string_type / int_parsingWrong type for the fieldPass the correct type
model_type / is_instance_ofv1 model into v2 APIAlign Pydantic imports to v2
From with_structured_outputModel JSON ≠ schemaDefaults, flatten, retry, stronger model
Did not find ..._api_keyAPI key not setSet env var / pass api_key
Optional field still "required"No default givenAdd = None

External References

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.

By Mohammad Wasi

Software Engineering Leader & Technical Author · Updated July 24, 2026


Related Posts