{"record":{"id":"db3e21cdfa87a253","repo":"langchain-ai/langchain","slug":"function-must-have-a-docstring-if-description-not","errorCode":null,"errorMessage":"Function must have a docstring if description not provided.","messagePattern":"Function must have a docstring if description not provided\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/tools/structured.py","lineNumber":235,"sourceCode":"                description_ = args_schema.__doc__\n                if (\n                    description_\n                    and \"A base class for creating Pydantic models\" in description_\n                ):\n                    description_ = \"\"\n                elif not description_:\n                    description_ = None\n            elif isinstance(args_schema, dict):\n                description_ = args_schema.get(\"description\")\n            else:\n                msg = (\n                    \"Invalid args_schema: expected BaseModel or dict, \"\n                    f\"got {args_schema}\"\n                )\n                raise TypeError(msg)\n        if description_ is None:\n            msg = \"Function must have a docstring if description not provided.\"\n            raise ValueError(msg)\n        if description is None:\n            # Only apply if using the function's docstring\n            description_ = textwrap.dedent(description_).strip()\n\n        # Description example:\n        # search_api(query: str) - Searches the API for the query.\n        description_ = f\"{description_.strip()}\"\n        return cls(\n            name=name,\n            func=func,\n            coroutine=coroutine,\n            args_schema=args_schema,\n            description=description_,\n            return_direct=return_direct,\n            response_format=response_format,\n            **kwargs,\n        )\n","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/tools/structured.py#L217-L253","documentation":"A tool must carry a description for the model; from_function derives it from the function's docstring when description is not given. If the function has no docstring, no description kwarg, and no description in a dict args_schema, construction fails with ValueError.","triggerScenarios":"StructuredTool.from_function(lambda x: x) (lambdas have no docstring) without description=; functions whose docstrings were stripped; dict args_schema lacking a 'description' key.","commonSituations":"Quick lambda-based tools; lint rules (e.g. D103) that don't require docstrings so devs omit them; automated tool generation from OpenAPI specs where the summary field was not mapped to description.","solutions":["Pass description= explicitly to from_function","Or add a docstring to the source function/coroutine","When using a dict args_schema, include a 'description' key"],"exampleFix":"# before\ntool = StructuredTool.from_function(\n    lambda q: search(q), name=\"search\"\n)\n\n# after\ntool = StructuredTool.from_function(\n    lambda q: search(q),\n    name=\"search\",\n    description=\"Search the web for a query.\",\n)","handlingStrategy":"validation","validationCode":"import inspect\n\ndef described_from_function(fn, **kw):\n    has_doc = bool(inspect.getdoc(fn))\n    schema_desc = isinstance(kw.get(\"args_schema\"), dict) and kw[\"args_schema\"].get(\"description\")\n    if not (kw.get(\"description\") or has_doc or schema_desc):\n        msg = f\"Tool {getattr(fn, '__name__', fn)!r} has no description or docstring\"\n        raise ValueError(msg)\n    return StructuredTool.from_function(fn, **kw)","typeGuard":null,"tryCatchPattern":"try:\n    t = StructuredTool.from_function(fn, name=name)\nexcept ValueError as e:\n    if \"docstring\" in str(e):\n        t = StructuredTool.from_function(fn, name=name, description=f\"TODO: {name}\")\n    else:\n        raise","preventionTips":["Require a docstring or description in your tool-authoring checklist","In CI, walk all registered tools and assert tool.description is non-empty","Map OpenAPI summary/description fields to description= when generating tools from specs"],"tags":["langchain","tools","docstring","structured-tool"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}