{"record":{"id":"008989a7edde9867","repo":"langchain-ai/langchain","slug":"name-must-be-a-string-for-tool-constructor","errorCode":null,"errorMessage":"Name must be a string for tool constructor","messagePattern":"Name must be a string for tool constructor","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/tools/convert.py","lineNumber":367,"sourceCode":"        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 \"\n        raise ValueError(msg)\n\n    if runnable is not None:\n        # tool is used as a function\n        # for instance tool_from_runnable = tool(\"name\", runnable)\n        if not name_or_callable:\n            msg = \"Runnable without name for tool constructor\"\n            raise ValueError(msg)\n        if not isinstance(name_or_callable, str):\n            msg = \"Name must be a string for tool constructor\"\n            raise ValueError(msg)\n        return _create_tool_factory(name_or_callable)(runnable)\n    if name_or_callable is not None:\n        if callable(name_or_callable) and hasattr(name_or_callable, \"__name__\"):\n            # Used as a decorator without parameters\n            # @tool\n            # def my_tool():\n            #    pass\n            return _create_tool_factory(name_or_callable.__name__)(name_or_callable)\n        if isinstance(name_or_callable, str):\n            # Used with a new name for the tool\n            # @tool(\"search\")\n            # def my_tool():\n            #    pass\n            #\n            # or\n            #\n            # @tool(\"search\", parse_docstring=True)\n            # def my_tool():","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/tools/convert.py#L349-L385","documentation":"In tool(name_or_callable, runnable=...) function-style usage, the first argument must be a string naming the tool. This raises when something other than a str (e.g. the function itself or a Runnable) was passed positionally together with runnable=.","triggerScenarios":"tool(my_func, runnable=my_runnable); tool(my_runnable, runnable=my_runnable); any non-string first argument combined with the runnable keyword.","commonSituations":"Mixing decorator-style and function-style usage in one call; passing both a callable and a runnable expecting them to be composed.","solutions":["Use only a string name with runnable=: tool('name', runnable=runnable)","To wrap a function, use the decorator form or call the factory: tool('name')(my_func)","To compose runnables, pipe them first (a | b) and then convert the composed chain"],"exampleFix":"# before\nt = tool(my_func, runnable=my_runnable)\n\n# after\nt = tool(\"my_tool\", runnable=my_runnable | my_func)","handlingStrategy":"type-guard","validationCode":"def tool_from_runnable(runnable, name):\n    if not isinstance(name, str):\n        msg = f\"name must be str, got {type(name).__name__}\"\n        raise TypeError(msg)\n    return tool(name, runnable=runnable)","typeGuard":"def is_str_name(x: object) -> bool:\n    return isinstance(x, str) and bool(x)","tryCatchPattern":"try:\n    t = tool(first_arg, runnable=runnable)\nexcept ValueError as e:\n    if \"Name must be a string\" in str(e):\n        t = tool(str(first_arg), runnable=runnable)\n    else:\n        raise","preventionTips":["When using runnable=, make the first argument a literal string name","Never pass the callable positionally together with runnable=","Review tool() call sites during code review for mixed positional/keyword misuse"],"tags":["langchain","tools","runnable","api-misuse"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}