{"record":{"id":"4a354c960eb30598","repo":"OpenBMB/ChatDev","slug":"function-name-not-found","errorCode":null,"errorMessage":"Function {name} not found","messagePattern":"Function (.+?) not found","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"utils/function_manager.py","lineNumber":106,"sourceCode":"        return f\"{_MODULE_PREFIX}.{parts}_{unique_suffix}\"\n\n    def get_function(self, name: str) -> Optional[Callable]:\n        \"\"\"Get a function by name.\"\"\"\n        if not self._loaded:\n            self.load_functions()\n        return self.functions.get(name)\n\n    def has_function(self, name: str) -> bool:\n        \"\"\"Check if a function exists.\"\"\"\n        if not self._loaded:\n            self.load_functions()\n        return name in self.functions\n\n    def call_function(self, name: str, *args, **kwargs) -> Any:\n        \"\"\"Call a function by name with given arguments.\"\"\"\n        func = self.get_function(name)\n        if func is None:\n            raise ValueError(f\"Function {name} not found\")\n        return func(*args, **kwargs)\n\n    def list_functions(self) -> Dict[str, Callable]:\n        \"\"\"List all available functions.\"\"\"\n        if not self._loaded:\n            self.load_functions()\n        return self.functions.copy()\n\n    def reload_functions(self) -> None:\n        \"\"\"Reload all functions from the functions directory.\"\"\"\n        self.functions.clear()\n        self._loaded = False\n        self.load_functions()\n\n\n# Global function manager registry keyed by directory\n_function_managers: Dict[Path, FunctionManager] = {}\n","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/utils/function_manager.py#L88-L124","documentation":"FunctionManager.call_function resolves the name via get_function (which lazily loads functions) and raises ValueError when no function with that name was loaded from the functions directory. Indicates an unregistered name, not a failure inside the function itself.","triggerScenarios":"Calling call_function('my_func') when my_func.py is missing, starts with '_', sits under __pycache__, failed to import earlier, or the function is defined but named differently; also when functions were never loaded because load_functions raised earlier.","commonSituations":"LLM/tool layer hallucinates or mis-cases a function name; file added but server not restarted (in-memory registry stale); function file shadowed by a module-level import error that was swallowed.","solutions":["Verify with fm.list_functions() / fm.has_function(name) that the function is loaded","Fix the name spelling/case to match the loaded registry","Ensure the defining .py file doesn't start with '_' and the function is defined at module level, then call fm.refresh()","Check for import errors inside the function file preventing registration"],"exampleFix":"# before\nresult = fm.call_function(name, *args)\n# after\nif not fm.has_function(name):\n    raise UnknownFunction(name)\nresult = fm.call_function(name, *args)","handlingStrategy":"validation","validationCode":"fm.load_functions()\nif not fm.has_function(name):\n    raise UnknownFunction(name)","typeGuard":"def is_known_function(fm, name: str) -> bool:\n    fm.load_functions()\n    return fm.has_function(name)","tryCatchPattern":"try:\n    result = fm.call_function(name, *args)\nexcept ValueError as e:\n    if 'not found' in str(e):\n        handle_unknown_tool(name)  # e.g. refresh + retry once, or reject","preventionTips":["Expose fm.list_functions() to the tool-calling layer as the valid name set","Call fm.refresh() after deploying new function files","Validate LLM-provided tool names against the registry"],"tags":["functions","lookup","dynamic-loading"],"backgroundTag":"function-not-registered","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}