langchain-ai/langchain · error · TypeError
args_schema must be a subclass of pydantic BaseModel or a JS
Error message
args_schema must be a subclass of pydantic BaseModel or a JSON schema dict. Got: {kwargs['args_schema']}. What it means
`BaseTool.__init__` (via `validate`) rejects an `args_schema` value that is neither a Pydantic `BaseModel` subclass nor a plain dict (JSON schema). This catches typos like passing an instance instead of the class, or a non-schema object, before the tool ever runs.
Source
Thrown at libs/core/langchain_core/tools/base.py:591
def __init__(self, **kwargs: Any) -> None:
"""Initialize the tool.
Raises:
TypeError: If `args_schema` is not a subclass of pydantic `BaseModel` or
`dict`.
"""
if (
"args_schema" in kwargs
and kwargs["args_schema"] is not None
and not is_basemodel_subclass(kwargs["args_schema"])
and not isinstance(kwargs["args_schema"], dict)
):
msg = (
"args_schema must be a subclass of pydantic BaseModel or "
f"a JSON schema dict. Got: {kwargs['args_schema']}."
)
raise TypeError(msg)
super().__init__(**kwargs)
model_config = ConfigDict(
arbitrary_types_allowed=True,
)
@property
def is_single_input(self) -> bool:
"""Check if the tool accepts only a single input argument.
Returns:
`True` if the tool has only one input argument, `False` otherwise.
"""
keys = {k for k in self.args if k != "kwargs"}
return len(keys) == 1
@property
def args(self) -> dict[str, Any]:View on GitHub (pinned to e32fa9a52e)
Solutions
- Pass the Pydantic model class itself: `args_schema=MySchema` (no parentheses).
- For JSON schemas, pass the parsed dict: `args_schema={'type': 'object', 'properties': {...}}`.
- If you have a TypedDict/dataclass, convert it to a Pydantic model first.
Example fix
# before tool = Tool(name='search', func=fn, description='d', args_schema=SearchArgs()) # after tool = Tool(name='search', func=fn, description='d', args_schema=SearchArgs)
Defensive patterns
Strategy: type-guard
Validate before calling
from pydantic import BaseModel
def valid_args_schema(x) -> bool:
return x is None or (isinstance(x, type) and issubclass(x, BaseModel)) or (
isinstance(x, dict) and isinstance(x.get('type', 'object'), str)
)
assert valid_args_schema(schema_value) Type guard
from pydantic import BaseModel
import inspect
def is_basemodel_subclass(x) -> bool:
return inspect.isclass(x) and issubclass(x, BaseModel) Try / catch
try:
t = Tool(name='t', func=fn, description='d', args_schema=schema)
except TypeError as e:
if 'args_schema must be a subclass' in str(e):
t = Tool(name='t', func=fn, description='d',
args_schema=schema if isinstance(schema, type) else dict(schema))
else:
raise Prevention
- Pass the schema class, not an instance (no parentheses).
- JSON schemas must be actual dicts, not strings — json.loads first.
- Convert TypedDicts/dataclasses to Pydantic models before use.
When it happens
Trigger: `Tool(name='t', ..., args_schema=MySchema())` (instance instead of class); passing a string, a dataclass, or a Pydantic `BaseModel`-like object from another library as `args_schema`; passing a `TypedDict` or JSON string.
Common situations: Confusing the schema class with an instance; migrating from old dataclass-based tool schemas; passing a serialized schema (JSON string) instead of the parsed dict; passing `TypedDict` classes where only Pydantic models or raw JSON-schema dicts are supported.
Related errors
- 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
- Tool arguments must be specified as a dict, received: {res['
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/e37660d886a33f42.
Report an issue: GitHub.