{"record":{"id":"d0e0433e61d6edc5","repo":"FoundationAgents/MetaGPT","slug":"function-name-not-found","errorCode":null,"errorMessage":"{function_name} not found","messagePattern":"(.+?) not found","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"metagpt/actions/skill_action.py","lineNumber":113,"sourceCode":"        try:\n            rsp = await self.find_and_call_function(self.skill.name, args=self.args, **options)\n            self.rsp = Message(content=rsp, role=\"assistant\", cause_by=self)\n        except Exception as e:\n            logger.exception(f\"{e}, traceback:{traceback.format_exc()}\")\n            self.rsp = Message(content=f\"Error: {e}\", role=\"assistant\", cause_by=self)\n        return self.rsp\n\n    @staticmethod\n    async def find_and_call_function(function_name, args, **kwargs) -> str:\n        try:\n            module = importlib.import_module(\"metagpt.learn\")\n            function = getattr(module, function_name)\n            # Invoke function and return result\n            result = await function(**args, **kwargs)\n            return result\n        except (ModuleNotFoundError, AttributeError):\n            logger.error(f\"{function_name} not found\")\n            raise ValueError(f\"{function_name} not found\")\n","sourceCodeStart":95,"sourceCodeEnd":114,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/actions/skill_action.py#L95-L114","documentation":"SkillAction.find_and_call_function dispatches a skill by importing metagpt.learn and getattr-ing the function name on it. If the module import fails or the attribute does not exist (the skill was never registered/exported in metagpt/learn/__init__.py), it logs 'X not found' and re-raises as ValueError. Only skills explicitly exported by metagpt.learn (google_search, text_to_speech, text_to_image, text_to_embedding, skill_loader helpers) are callable.","triggerScenarios":"SkillAction.run with skill.name set to a function not exported from metagpt.learn (e.g. 'my_custom_skill' or a misspelled name), or when a custom skill exists in a plugin package but was not added to metagpt.learn's namespace.","commonSituations":"Writing new skills in your own module but expecting SkillAction to find them; name mismatches between the skill yaml/registry name and the python function name; version changes that rename or remove a learned skill.","solutions":["Verify the function exists: run python -c \"import metagpt.learn as m; print(hasattr(m, 'NAME'))\".","Add your custom skill function to metagpt/learn/__init__.py (or monkeypatch/extend it) so getattr succeeds.","Fix spelling/case of skill.name to exactly match the exported python function name."],"exampleFix":"# before\n# my_skill defined only in my_pkg/skills.py -> ValueError: my_skill not found\n\n# after\n# metagpt/learn/__init__.py\nfrom my_pkg.skills import my_skill  # now getattr(metagpt.learn, 'my_skill') works","handlingStrategy":"try-catch","validationCode":"import metagpt.learn as ml\nassert hasattr(ml, skill.name), f\"skill '{skill.name}' is not exported by metagpt.learn\"","typeGuard":"import metagpt.learn as _ml\ndef skill_exists(name: str) -> bool:\n    return hasattr(_ml, name)","tryCatchPattern":"try:\n    result = await SkillAction.find_and_call_function(name, args)\nexcept ValueError as e:\n    if 'not found' in str(e):\n        logger.warning('skill missing, falling back')\n        result = await fallback_handler(name, args)","preventionTips":["Register custom skills in metagpt.learn's namespace before use.","Validate skill names against metagpt.learn exports at startup.","Pin skill names from a config checklist rather than free text."],"tags":["skills","dynamic-import","registry","action"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}