langchain-ai/langchain · error · ValueError
Too many arguments for tool decorator. A decorator
Error message
Too many arguments for tool decorator. A decorator
What it means
The @tool decorator accepts at most one positional argument (a name string or the function itself). This error means extra positional arguments were passed, i.e. the decorator was used with a signature the API does not support — everything besides the first positional must be keyword-only.
Source
Thrown at libs/core/langchain_core/tools/convert.py:357
return Tool(
name=tool_name,
func=func,
description=tool_description,
return_direct=return_direct,
coroutine=coroutine,
response_format=response_format,
extras=extras,
)
return _tool_factory
if len(args) != 0:
# Triggered if a user attempts to use positional arguments that
# do not exist in the function signature
# e.g., @tool("name", runnable, "extra_arg")
# Here, "extra_arg" is not a valid argument
msg = "Too many arguments for tool decorator. A decorator "
raise ValueError(msg)
if runnable is not None:
# tool is used as a function
# for instance tool_from_runnable = tool("name", runnable)
if not name_or_callable:
msg = "Runnable without name for tool constructor"
raise ValueError(msg)
if not isinstance(name_or_callable, str):
msg = "Name must be a string for tool constructor"
raise ValueError(msg)
return _create_tool_factory(name_or_callable)(runnable)
if name_or_callable is not None:
if callable(name_or_callable) and hasattr(name_or_callable, "__name__"):
# Used as a decorator without parameters
# @tool
# def my_tool():
# pass
return _create_tool_factory(name_or_callable.__name__)(name_or_callable)View on GitHub (pinned to e32fa9a52e)
Solutions
- Pass only the name positionally and everything else by keyword: @tool('search', return_direct=True)
- To convert a Runnable, use tool('name', runnable=runnable)
- To decorate a function, apply @tool directly or @tool('name') — never pass the function positionally to tool()
Example fix
# before
my_tool = tool("search", my_func, True)
# after
my_tool = tool("search", return_direct=True)(my_func)
# or
@tool("search", return_direct=True)
def my_func(query: str) -> str: ... Defensive patterns
Strategy: validation
Validate before calling
import inspect
def safe_tool_call(*args, **kwargs):
"""Enforce @tool's one-positional-argument contract."""
if len(args) > 1:
msg = "tool() takes at most 1 positional argument; pass the rest by keyword"
raise TypeError(msg)
return tool(*args, **kwargs) Try / catch
try:
t = tool("name", func, True)
except ValueError as e:
if "Too many arguments" in str(e):
t = tool("name", return_direct=True)(func)
else:
raise Prevention
- Use the decorator form (@tool or @tool('name')) instead of calling tool() positionally
- Pass Runnables via the runnable= keyword only
- Treat any second positional argument to tool() as a bug
When it happens
Trigger: @tool('name', runnable, 'extra') or tool('name', func, True); any call to tool(...) with len(args) > 1 positionally.
Common situations: Assuming @tool supports positional (name, func) style like older or different APIs; copy-pasting decorator usage from another library; typos adding stray positional args.
Related errors
- Runnable without name for tool constructor
- Name must be a string for tool constructor
- The first argument must be a string or a callable with a __n
- Runnable must have an object schema.
- Function must have either a docstring or description when in
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/d7ff684ab295c057.
Report an issue: GitHub.