{"record":{"id":"920e7fa9aaa6a07e","repo":"FoundationAgents/MetaGPT","slug":"api-name-api-name-not-found","errorCode":null,"errorMessage":"api_name: {api_name} not found","messagePattern":"api_name: (.+?) not found","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"metagpt/environment/api/env_api.py","lineNumber":25,"sourceCode":"from pydantic import BaseModel, Field\n\n\nclass EnvAPIAbstract(BaseModel):\n    \"\"\"api/interface summary description\"\"\"\n\n    api_name: str = Field(default=\"\", description=\"the api function name or id\")\n    args: set = Field(default={}, description=\"the api function `args` params\")\n    kwargs: dict = Field(default=dict(), description=\"the api function `kwargs` params\")\n\n\nclass EnvAPIRegistry(BaseModel):\n    \"\"\"the registry to store environment w&r api/interface\"\"\"\n\n    registry: dict[str, Callable] = Field(default=dict(), exclude=True)\n\n    def get(self, api_name: str):\n        if api_name not in self.registry:\n            raise KeyError(f\"api_name: {api_name} not found\")\n        return self.registry.get(api_name)\n\n    def __getitem__(self, api_name: str) -> Callable:\n        return self.get(api_name)\n\n    def __setitem__(self, api_name: str, func: Callable):\n        self.registry[api_name] = func\n\n    def __len__(self):\n        return len(self.registry)\n\n    def get_apis(self, as_str=True) -> dict[str, dict[str, Union[dict, Any, str]]]:\n        \"\"\"return func schema without func instance\"\"\"\n        apis = dict()\n        for func_name, func_schema in self.registry.items():\n            new_func_schema = dict()\n            for key, value in func_schema.items():\n                if key == \"func\":","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/environment/api/env_api.py#L7-L43","documentation":"EnvAPIRegistry.get raises KeyError('api_name: {name} not found') when the requested name is not in its registry dict. The registry is populated via __setitem__ / registration decorators by each ExtEnv implementation, so the error means the environment you are using never registered an API with that name (or you are querying the wrong registry — read vs write).","triggerScenarios":"env.read_from_api(\"some_api\") or accessing env.api_registry[\"some_api\"] where 'some_api' was never registered; calling a write API name against the read registry or vice versa; typo in the api_name string; using an ExtEnv subclass that does not implement that API.","commonSituations":"Copying example code from a different environment (e.g. a Minecraft API name used against the Android env); version changes that renamed or removed registered APIs; querying APIs before the environment instance registered them.","solutions":["List what is actually available: env.get_all_available_apis(mode='read') and mode='write' return the registered names and definitions.","Match the mode: read APIs go through read_from_api, write APIs through write_to_api — using the wrong side raises this KeyError.","Check for typos and for the exact registered spelling (some names include prefixes/suffixes).","If the API genuinely should exist, upgrade/downgrade MetaGPT to the version whose environment registers it, or register it yourself via registry[\"name\"] = func."],"exampleFix":"# before\nobs = await env.read_from_api(\"get_inventories\")  # KeyError: api_name: get_inventories not found\n\n# after\navailable = env.get_all_available_apis(mode=\"read\")\nassert \"get_inventory\" in available, f\"known read apis: {list(available)}\"\nobs = await env.read_from_api(\"get_inventory\")","handlingStrategy":"validation","validationCode":"available = env.get_all_available_apis(mode=\"read\")\nif api_name not in available:\n    raise KeyError(f\"{api_name!r} not registered; available: {sorted(available)}\")\nobs = await env.read_from_api(api_name)","typeGuard":"def api_exists(env, api_name: str, mode: str = \"read\") -> bool:\n    \"\"\"True when the environment registered api_name for the given mode.\"\"\"\n    registry = env_read_api_registry if mode == \"read\" else env_write_api_registry\n    return api_name in registry.registry","tryCatchPattern":"try:\n    obs = await env.read_from_api(api_name)\nexcept KeyError as e:\n    known = sorted(env.get_all_available_apis(mode=\"read\"))\n    raise KeyError(f\"unknown api {api_name!r}; registered read apis: {known}\") from e","preventionTips":["Print get_all_available_apis() for both modes once per environment and drive calls from that list.","Keep api names as constants shared between registration and call sites instead of hand-typed strings.","Match read vs write registries — querying the wrong side is the most common miss."],"tags":["python","registry","api-lookup","environment","keyerror"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}