langchain-ai/langchain · error · NotImplementedError
Function {func} contains a mix of Pydantic v1 and v2 annotat
Error message
Function {func} contains a mix of Pydantic v1 and v2 annotations. Only one version of Pydantic annotations per function is supported. What it means
When inferring a tool schema from a function, langchain checks each parameter annotation for Pydantic v1 vs v2 models and refuses functions that mix both (e.g. one arg annotated with a `pydantic.v1.BaseModel` subclass and another with a `pydantic.BaseModel` subclass), raising NotImplementedError because a single schema cannot be generated across both major versions.
Source
Thrown at libs/core/langchain_core/tools/base.py:250
True if all Pydantic annotations are from v1, `False` otherwise.
Raises:
NotImplementedError: If the function contains mixed v1 and v2 annotations.
"""
any_v1_annotations = any(
_is_pydantic_annotation(parameter.annotation, pydantic_version="v1")
for parameter in signature.parameters.values()
)
any_v2_annotations = any(
_is_pydantic_annotation(parameter.annotation, pydantic_version="v2")
for parameter in signature.parameters.values()
)
if any_v1_annotations and any_v2_annotations:
msg = (
f"Function {func} contains a mix of Pydantic v1 and v2 annotations. "
"Only one version of Pydantic annotations per function is supported."
)
raise NotImplementedError(msg)
return any_v1_annotations and not any_v2_annotations
class _SchemaConfig:
"""Configuration for Pydantic models generated from function signatures."""
extra: str = "forbid"
"""Whether to allow extra fields in the model."""
arbitrary_types_allowed: bool = True
"""Whether to allow arbitrary types in the model."""
def create_schema_from_function(
model_name: str,
func: Callable[..., Any],
*,
filter_args: Sequence[str] | None = None,View on GitHub (pinned to e32fa9a52e)
Solutions
- Migrate all parameter models to one Pydantic major version — preferably v2 (`pydantic.BaseModel`).
- Check each annotation's module (`type(x).__module__`) to find the v1 stragglers, often imported from a dependency pinned to `pydantic.v1`.
- If a dependency only offers v1 models, wrap its inputs in a plain v2 model or primitive types at the tool boundary.
- If mixed versions are unavoidable, supply an explicit `args_schema` (single-version) instead of relying on inference.
Example fix
# before from pydantic.v1 import BaseModel as V1Base from pydantic import BaseModel class A(V1Base): x: int class B(BaseModel): y: int @tool def f(a: A, b: B) -> str: ... # NotImplementedError # after from pydantic import BaseModel class A(BaseModel): x: int class B(BaseModel): y: int @tool def f(a: A, b: B) -> str: ...
Defensive patterns
Strategy: type-guard
Validate before calling
import inspect, pydantic
def annotations_single_pydantic_version(fn) -> bool:
versions = set()
for p in inspect.signature(fn).parameters.values():
ann = p.annotation
mod = getattr(ann, '__module__', '')
if 'pydantic' in mod:
versions.add('v1' if mod.startswith('pydantic.v1') else 'v2')
return len(versions) <= 1
assert annotations_single_pydantic_version(fn) Type guard
import pydantic, pydantic.v1
def is_pydantic_v2_model(cls) -> bool:
return inspect.isclass(cls) and issubclass(cls, pydantic.BaseModel)
def is_pydantic_v1_model(cls) -> bool:
return inspect.isclass(cls) and issubclass(cls, pydantic.v1.BaseModel) Try / catch
try:
t = tool(fn)
except NotImplementedError as e:
if 'Pydantic v1 and v2' in str(e):
fn = migrate_annotations_to_v2(fn) # retype params, then retry
t = tool(fn)
else:
raise Prevention
- Migrate all models to pydantic v2; grep for 'pydantic.v1' imports.
- Check type(x).__module__ of annotation models when mixing dependencies.
- Supply explicit args_schema when a dependency is stuck on v1.
When it happens
Trigger: `@tool def f(a: MyV1Model, b: MyV2Model)` where `MyV1Model` inherits `pydantic.v1.BaseModel`; a function annotated with a model imported from a package still on Pydantic v1 alongside a locally-defined v2 model.
Common situations: Migrating a codebase (or a dependency) to Pydantic v2 while some imports still resolve to `pydantic.v1`; partner/integration packages that expose v1 models; notebooks where an old model class lingers after upgrading pydantic.
Related errors
- args_schema must be a subclass of pydantic BaseModel or a JS
- Either data or path must be provided
- ToolMessage content should be a string or a list of string/d
- If multiple pydantic schemas are provided then args_only sho
- Dict Pydantic schema unsupported with args_only: {self.pydan
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/0f505e5e0777c679.
Report an issue: GitHub.