{"record":{"id":"e37660d886a33f42","repo":"langchain-ai/langchain","slug":"args-schema-must-be-a-subclass-of-pydantic-basemod","errorCode":null,"errorMessage":"args_schema must be a subclass of pydantic BaseModel or a JSON schema dict. Got: {kwargs['args_schema']}.","messagePattern":"args_schema must be a subclass of pydantic BaseModel or a JSON schema dict\\. Got: (.+?)\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/tools/base.py","lineNumber":591,"sourceCode":"\n    def __init__(self, **kwargs: Any) -> None:\n        \"\"\"Initialize the tool.\n\n        Raises:\n            TypeError: If `args_schema` is not a subclass of pydantic `BaseModel` or\n                `dict`.\n        \"\"\"\n        if (\n            \"args_schema\" in kwargs\n            and kwargs[\"args_schema\"] is not None\n            and not is_basemodel_subclass(kwargs[\"args_schema\"])\n            and not isinstance(kwargs[\"args_schema\"], dict)\n        ):\n            msg = (\n                \"args_schema must be a subclass of pydantic BaseModel or \"\n                f\"a JSON schema dict. Got: {kwargs['args_schema']}.\"\n            )\n            raise TypeError(msg)\n        super().__init__(**kwargs)\n\n    model_config = ConfigDict(\n        arbitrary_types_allowed=True,\n    )\n\n    @property\n    def is_single_input(self) -> bool:\n        \"\"\"Check if the tool accepts only a single input argument.\n\n        Returns:\n            `True` if the tool has only one input argument, `False` otherwise.\n        \"\"\"\n        keys = {k for k in self.args if k != \"kwargs\"}\n        return len(keys) == 1\n\n    @property\n    def args(self) -> dict[str, Any]:","sourceCodeStart":573,"sourceCodeEnd":609,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/tools/base.py#L573-L609","documentation":"`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.","triggerScenarios":"`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.","commonSituations":"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.","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."],"exampleFix":"# before\ntool = Tool(name='search', func=fn, description='d', args_schema=SearchArgs())\n# after\ntool = Tool(name='search', func=fn, description='d', args_schema=SearchArgs)","handlingStrategy":"type-guard","validationCode":"from pydantic import BaseModel\n\ndef valid_args_schema(x) -> bool:\n    return x is None or (isinstance(x, type) and issubclass(x, BaseModel)) or (\n        isinstance(x, dict) and isinstance(x.get('type', 'object'), str)\n    )\n\nassert valid_args_schema(schema_value)","typeGuard":"from pydantic import BaseModel\nimport inspect\n\ndef is_basemodel_subclass(x) -> bool:\n    return inspect.isclass(x) and issubclass(x, BaseModel)","tryCatchPattern":"try:\n    t = Tool(name='t', func=fn, description='d', args_schema=schema)\nexcept TypeError as e:\n    if 'args_schema must be a subclass' in str(e):\n        t = Tool(name='t', func=fn, description='d',\n                 args_schema=schema if isinstance(schema, type) else dict(schema))\n    else:\n        raise","preventionTips":["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."],"tags":["tool","args-schema","validation","pydantic"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}