{"record":{"id":"da09ecebe0f58664","repo":"langchain-ai/langchain","slug":"function-and-or-coroutine-must-be-provided-da09ec","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/structured.py","lineNumber":201,"sourceCode":"            TypeError: If the `args_schema` is not a `BaseModel` or dict.\n\n        Examples:\n            ```python\n            def add(a: int, b: int) -> int:\n                \\\"\\\"\\\"Add two numbers\\\"\\\"\\\"\n                return a + b\n            tool = StructuredTool.from_function(add)\n            tool.run(1, 2) # 3\n\n            ```\n        \"\"\"\n        if func is not None:\n            source_function = func\n        elif coroutine is not None:\n            source_function = coroutine\n        else:\n            msg = \"Function and/or coroutine must be provided\"\n            raise ValueError(msg)\n        name = name or source_function.__name__\n        if args_schema is None and infer_schema:\n            # schema name is appended within function\n            args_schema = create_schema_from_function(\n                name,\n                source_function,\n                parse_docstring=parse_docstring,\n                error_on_invalid_docstring=error_on_invalid_docstring,\n                filter_args=_filter_schema_args(source_function),\n            )\n        description_ = description\n        if description is None and not parse_docstring:\n            description_ = source_function.__doc__ or None\n        if description_ is None and args_schema:\n            if isinstance(args_schema, type) and is_basemodel_subclass(args_schema):\n                description_ = args_schema.__doc__\n                if (\n                    description_","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/tools/structured.py#L183-L219","documentation":"StructuredTool.from_function uses func or coroutine both as the executable and as the source of the name and schema. With neither provided there is no source_function, so construction aborts with ValueError before any schema inference.","triggerScenarios":"StructuredTool.from_function() with neither func nor coroutine; conditional code paths that pass func only when a lookup succeeds and silently forward None.","commonSituations":"Factory functions mapping config entries to tools where the callable registration failed; refactoring from_function calls and dropping the first argument.","solutions":["Supply func (sync) and/or coroutine (async) to from_function","Guard dynamic construction: raise early if the resolved callable is None","For pure data tools, subclass StructuredTool and implement _run/_arun instead"],"exampleFix":"# before\nfn = registry.get(tool_cfg.name)      # may return None\ntool = StructuredTool.from_function(fn, name=tool_cfg.name)\n\n# after\nfn = registry.get(tool_cfg.name)\nif fn is None:\n    msg = f\"Unknown tool {tool_cfg.name}\"\n    raise KeyError(msg)\ntool = StructuredTool.from_function(fn, name=tool_cfg.name)","handlingStrategy":"validation","validationCode":"def structured_tool_from(fn, **kw):\n    if not callable(fn):\n        msg = f\"from_function needs a callable, got {fn!r}\"\n        raise TypeError(msg)\n    return StructuredTool.from_function(fn, **kw)","typeGuard":"from collections.abc import Callable\n\ndef is_tool_source(fn: object) -> bool:\n    return callable(fn) and hasattr(fn, \"__name__\")","tryCatchPattern":"try:\n    t = StructuredTool.from_function(source, name=name)\nexcept ValueError as e:\n    if \"must be provided\" in str(e):\n        msg = f\"Tool source for {name!r} resolved to None\"\n        raise RuntimeError(msg) from e\n    raise","preventionTips":["Resolve callables at registration and hard-fail on None instead of forwarding","Type tool-factory inputs as Callable | Coroutine so None fails static checks","Write a startup smoke test that instantiates every registered tool"],"tags":["langchain","tools","structured-tool","validation"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}