{"record":{"id":"05a2e68ec7d109da","repo":"langchain-ai/langchain","slug":"function-and-or-coroutine-must-be-provided","errorCode":null,"errorMessage":"Function and/or coroutine must be provided","messagePattern":"Function and/or coroutine must be provided","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/tools/simple.py","lineNumber":199,"sourceCode":"\n        Args:\n            func: The function to create the tool from.\n            name: The name of the tool.\n            description: The description of the tool.\n            return_direct: Whether to return the output directly.\n            args_schema: The schema of the tool's input arguments.\n            coroutine: The asynchronous version of the function.\n            **kwargs: Additional arguments to pass to the tool.\n\n        Returns:\n            The tool.\n\n        Raises:\n            ValueError: If the function is not provided.\n        \"\"\"\n        if func is None and coroutine is None:\n            msg = \"Function and/or coroutine must be provided\"\n            raise ValueError(msg)\n        return cls(\n            name=name,\n            func=func,\n            coroutine=coroutine,\n            description=description,\n            return_direct=return_direct,\n            args_schema=args_schema,\n            **kwargs,\n        )\n","sourceCodeStart":181,"sourceCodeEnd":209,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/tools/simple.py#L181-L209","documentation":"StructuredTool.from_function requires at least one of func or coroutine; passing neither leaves the tool with nothing to execute, so creation fails immediately with ValueError.","triggerScenarios":"StructuredTool.from_function(name='t', description='...') with no func/coroutine; passing func=None explicitly and omitting coroutine.","commonSituations":"Building tools from configuration where the function reference failed to resolve (None from a factory); subclass scaffolding copy-paste where the function argument was dropped.","solutions":["Pass a function: StructuredTool.from_function(my_func)","If constructing from a class, pass the callable explicitly (e.g. instance.method)","Add an assert func is not None or coroutine is not None before the call in dynamic tool factories"],"exampleFix":"# before\ntool = StructuredTool.from_function(\n    name=\"t\", description=\"...\", func=None\n)\n\n# after\nasync def run(query: str) -> str: ...\ntool = StructuredTool.from_function(\n    name=\"t\", description=\"...\", coroutine=run\n)","handlingStrategy":"validation","validationCode":"def build_structured_tool(func=None, coroutine=None, **kw):\n    if func is None and coroutine is None:\n        msg = \"Refusing to create a tool with no implementation\"\n        raise ValueError(msg)\n    return StructuredTool.from_function(func=func, coroutine=coroutine, **kw)","typeGuard":"def has_implementation(func: object, coroutine: object) -> bool:\n    return callable(func) or callable(coroutine)","tryCatchPattern":"try:\n    t = StructuredTool.from_function(**tool_kwargs)\nexcept ValueError as e:\n    if \"must be provided\" in str(e):\n        tool_kwargs[\"func\"] = default_noop\n        t = StructuredTool.from_function(**tool_kwargs)\n    else:\n        raise","preventionTips":["Assert callable resolution succeeded in registry/factory code before from_function","Fail fast at registration time, not at first tool use","Annotate factory parameters as Callable to let mypy flag None paths"],"tags":["langchain","tools","validation","structured-tool"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}