{"record":{"id":"4ce791a4c6abdb9c","repo":"langchain-ai/langchain","slug":"function-must-have-either-a-docstring-or-descripti","errorCode":null,"errorMessage":"Function must have either a docstring or description when infer_schema is False.","messagePattern":"Function must have either a docstring or description when infer_schema is False\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/tools/convert.py","lineNumber":338,"sourceCode":"                    name=tool_name,\n                    description=tool_description,\n                    return_direct=return_direct,\n                    args_schema=schema,\n                    infer_schema=infer_schema,\n                    response_format=response_format,\n                    parse_docstring=parse_docstring,\n                    error_on_invalid_docstring=error_on_invalid_docstring,\n                    extras=extras,\n                )\n            # If someone doesn't want a schema applied, we must treat it as\n            # a simple string->string function\n            tool_description = tool_description or dec_func.__doc__\n            if tool_description is None:\n                msg = (\n                    \"Function must have either a docstring or description \"\n                    \"when infer_schema is False.\"\n                )\n                raise ValueError(msg)\n            return Tool(\n                name=tool_name,\n                func=func,\n                description=tool_description,\n                return_direct=return_direct,\n                coroutine=coroutine,\n                response_format=response_format,\n                extras=extras,\n            )\n\n        return _tool_factory\n\n    if len(args) != 0:\n        # Triggered if a user attempts to use positional arguments that\n        # do not exist in the function signature\n        # e.g., @tool(\"name\", runnable, \"extra_arg\")\n        # Here, \"extra_arg\" is not a valid argument\n        msg = \"Too many arguments for tool decorator. A decorator \"","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/tools/convert.py#L320-L356","documentation":"With infer_schema=False the @tool decorator cannot derive a description from a schema, so the target function's docstring (or an explicit description argument) is mandatory — a tool with no description is unusable for models. This check enforces that requirement at creation time.","triggerScenarios":"@tool(infer_schema=False) applied to a function with no docstring and no description=... passed to the decorator; same when calling tool(func, infer_schema=False).","commonSituations":"Quickly stubbing a tool function without a docstring; teams disabling schema inference for tight control over schemas but forgetting the description; copy-pasted functions stripped of docstrings by a linter.","solutions":["Add a docstring to the decorated function","Or pass description explicitly: @tool(infer_schema=False, description='Does X')","Re-enable infer_schema if schema-derived description was intended"],"exampleFix":"# before\n@tool(infer_schema=False)\ndef lookup(id: str) -> str:\n    return db.get(id)\n\n# after\n@tool(infer_schema=False, description=\"Look up a record by id.\")\ndef lookup(id: str) -> str:\n    return db.get(id)","handlingStrategy":"validation","validationCode":"def make_tool(func, *, description: str | None = None, infer_schema: bool = False):\n    description = description or (func.__doc__ or \"\").strip()\n    if not description:\n        msg = f\"Tool {getattr(func, '__name__', func)} needs a description or docstring\"\n        raise ValueError(msg)\n    return tool(func, description=description, infer_schema=infer_schema)","typeGuard":null,"tryCatchPattern":"try:\n    t = tool(func, infer_schema=False)\nexcept ValueError as e:\n    if \"docstring or description\" in str(e):\n        t = tool(func, description=\"TODO: describe this tool\", infer_schema=False)\n    else:\n        raise","preventionTips":["Adopt a project rule: every tool function gets a one-line docstring","In dynamic tool registries, validate description presence at registration time","Enable docstring linters (D100-series in ruff) for tool modules"],"tags":["langchain","tools","docstring","validation"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}