langchain-ai/langchain · error · ValueError
The first argument must be a string or a callable with a __n
Error message
The first argument must be a string or a callable with a __name__ for tool decorator. Got {type(name_or_callable)} What it means
The first positional argument of @tool must be either a string (tool name) or a callable with __name__ (the function to wrap). Anything else — int, None-likes without __name__, module, list — triggers this ValueError with the offending type.
Source
Thrown at libs/core/langchain_core/tools/convert.py:392
# pass
return _create_tool_factory(name_or_callable.__name__)(name_or_callable)
if isinstance(name_or_callable, str):
# Used with a new name for the tool
# @tool("search")
# def my_tool():
# pass
#
# or
#
# @tool("search", parse_docstring=True)
# def my_tool():
# pass
return _create_tool_factory(name_or_callable)
msg = (
f"The first argument must be a string or a callable with a __name__ "
f"for tool decorator. Got {type(name_or_callable)}"
)
raise ValueError(msg)
# Tool is used as a decorator with parameters specified
# @tool(parse_docstring=True)
# def my_tool():
# pass
def _partial(func: Callable[..., Any] | Runnable[Any, Any]) -> BaseTool:
"""Partial function that takes a `Callable` and returns a tool."""
name_ = func.get_name() if isinstance(func, Runnable) else func.__name__
tool_factory = _create_tool_factory(name_)
return tool_factory(func)
return _partial
def _get_description_from_runnable(runnable: Runnable[Any, Any]) -> str:
"""Generate a placeholder description of a `Runnable`."""
input_schema = runnable.get_input_jsonschema()
return f"Takes {input_schema}."View on GitHub (pinned to e32fa9a52e)
Solutions
- Pass a string name or the decorated function itself positionally
- For Runnables use tool(name, runnable=runnable)
- Sanitize dynamically generated names: assert isinstance(name, str) and name before calling tool()
Example fix
# before name = get_tool_name() # returns 42 or None t = tool(name)(my_func) # after name = get_tool_name() assert isinstance(name, str) and name, "tool name must be a non-empty string" t = tool(name)(my_func)
Defensive patterns
Strategy: type-guard
Validate before calling
def validate_tool_arg(arg) -> str:
if isinstance(arg, str) and arg:
return arg
if callable(arg) and hasattr(arg, "__name__"):
return arg.__name__
msg = f"Bad @tool argument: {arg!r} of type {type(arg)}"
raise TypeError(msg) Type guard
def is_valid_first_tool_arg(x: object) -> bool:
return (isinstance(x, str) and bool(x)) or (callable(x) and hasattr(x, "__name__")) Try / catch
try:
t = tool(maybe_name)(func)
except ValueError as e:
if "first argument" in str(e):
t = tool("default_name")(func)
else:
raise Prevention
- In dynamic code, branch explicitly on isinstance(name_or_callable, str) before calling tool()
- Never pass Runnables positionally; use runnable=
- Add type annotations (str | Callable) at tool-factory boundaries so mypy catches misuse
When it happens
Trigger: tool(123); tool(['a','b']); tool(SomeClassWithoutName); passing a variable holding a non-callable as the first argument.
Common situations: Programmatic tool creation where a name variable is accidentally None or a non-string; passing a Runnable positionally instead of via runnable=; refactors that change what the first argument holds.
Related errors
- Function must have either a docstring or description when in
- Too many arguments for tool decorator. A decorator
- Runnable without name for tool constructor
- Name must be a string for tool constructor
- Function and/or coroutine must be provided
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/c15feb920014b722.
Report an issue: GitHub.