langchain-ai/langchain · error · ValueError
Function must have a docstring if description not provided.
Error message
Function must have a docstring if description not provided.
What it means
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.
Source
Thrown at libs/core/langchain_core/tools/structured.py:235
description_ = args_schema.__doc__
if (
description_
and "A base class for creating Pydantic models" in description_
):
description_ = ""
elif not description_:
description_ = None
elif isinstance(args_schema, dict):
description_ = args_schema.get("description")
else:
msg = (
"Invalid args_schema: expected BaseModel or dict, "
f"got {args_schema}"
)
raise TypeError(msg)
if description_ is None:
msg = "Function must have a docstring if description not provided."
raise ValueError(msg)
if description is None:
# Only apply if using the function's docstring
description_ = textwrap.dedent(description_).strip()
# Description example:
# search_api(query: str) - Searches the API for the query.
description_ = f"{description_.strip()}"
return cls(
name=name,
func=func,
coroutine=coroutine,
args_schema=args_schema,
description=description_,
return_direct=return_direct,
response_format=response_format,
**kwargs,
)
View on GitHub (pinned to e32fa9a52e)
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
Example fix
# before
tool = StructuredTool.from_function(
lambda q: search(q), name="search"
)
# after
tool = StructuredTool.from_function(
lambda q: search(q),
name="search",
description="Search the web for a query.",
) Defensive patterns
Strategy: validation
Validate before calling
import inspect
def described_from_function(fn, **kw):
has_doc = bool(inspect.getdoc(fn))
schema_desc = isinstance(kw.get("args_schema"), dict) and kw["args_schema"].get("description")
if not (kw.get("description") or has_doc or schema_desc):
msg = f"Tool {getattr(fn, '__name__', fn)!r} has no description or docstring"
raise ValueError(msg)
return StructuredTool.from_function(fn, **kw) Try / catch
try:
t = StructuredTool.from_function(fn, name=name)
except ValueError as e:
if "docstring" in str(e):
t = StructuredTool.from_function(fn, name=name, description=f"TODO: {name}")
else:
raise Prevention
- 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
When it happens
Trigger: StructuredTool.from_function(lambda x: x) (lambdas have no docstring) without description=; functions whose docstrings were stripped; dict args_schema lacking a 'description' key.
Common situations: 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.
Related errors
- Function must have either a docstring or description when in
- Function and/or coroutine must be provided
- StructuredTool does not support sync invocation.
- Function and/or coroutine must be provided
- Runnable must have an object schema.
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/db3e21cdfa87a253.
Report an issue: GitHub.