FoundationAgents/MetaGPT · error · ValueError
{rw_api} not exists
Error message
{rw_api} not exists What it means
ExtEnv._check_api_exist raises ValueError('{rw_api} not exists') when the argument is falsy — None or an empty string. Despite the message showing the value, the only failing condition is `not rw_api`; a non-empty string always passes this check (existence in the registry is enforced separately by EnvAPIRegistry.get). It is a guard against calling read/write APIs without specifying which one.
Source
Thrown at metagpt/environment/base_env.py:63
def mark_as_writeable(func):
"""mark functionn as a writeable one in ExtEnv, it does something to ExtEnv"""
env_write_api_registry[func.__name__] = get_function_schema(func)
return func
class ExtEnv(BaseEnvironment, BaseModel):
"""External Env to integrate actual game environment"""
model_config = ConfigDict(arbitrary_types_allowed=True)
action_space: spaces.Space[ActType] = Field(default_factory=spaces.Space, exclude=True)
observation_space: spaces.Space[ObsType] = Field(default_factory=spaces.Space, exclude=True)
def _check_api_exist(self, rw_api: Optional[str] = None):
if not rw_api:
raise ValueError(f"{rw_api} not exists")
def get_all_available_apis(self, mode: str = "read") -> list[Any]:
"""get available read/write apis definition"""
assert mode in ["read", "write"]
if mode == "read":
return env_read_api_registry.get_apis()
else:
return env_write_api_registry.get_apis()
async def read_from_api(self, env_action: Union[str, EnvAPIAbstract]):
"""get observation from particular api of ExtEnv"""
if isinstance(env_action, str):
env_read_api = env_read_api_registry.get(api_name=env_action)["func"]
self._check_api_exist(env_read_api)
if is_coroutine_func(env_read_api):
res = await env_read_api(self)
else:
res = env_read_api(self)View on GitHub (pinned to 11cdf466d0)
Solutions
- Always pass a concrete api name string: await env.read_from_api("api_name") or a fully-populated EnvAPIAbstract.
- If building action objects dynamically, assert api_name is non-empty before calling the env.
- When accepting api names from config/user input, validate non-empty at the boundary with a clear error.
Example fix
# before
obs = await env.read_from_api("") # ValueError: not exists
# after
api_name = "get_map"
assert api_name, "api name must be a non-empty string"
obs = await env.read_from_api(api_name) Defensive patterns
Strategy: validation
Validate before calling
if not rw_api or not isinstance(rw_api, str):
raise ValueError("an api name (non-empty str) is required before calling read/write APIs") Type guard
def is_valid_api_name(name) -> bool:
"""True when name passes ExtEnv._check_api_exist's falsy check."""
return isinstance(name, str) and bool(name) Try / catch
try:
await env.read_from_api(api_name)
except ValueError as e:
if "not exists" in str(e):
raise ValueError("api name was None/empty; populate api_name before calling") from e
raise Prevention
- Set api_name explicitly on every EnvAPIAbstract subclass instead of relying on its "" default.
- Assert the name is a non-empty string at your call boundary.
- Derive api names from a validated source (config enum, registry listing), never from unvalidated user input.
When it happens
Trigger: await env.read_from_api(None) or env.read_from_api("") — e.g. an EnvAPIAbstract whose api_name field defaulted to "", or a variable that failed to populate and defaulted to None.
Common situations: Constructing EnvAPIAbstract subclasses without setting api_name (it defaults to ""); passing a programmatically-derived api name that resolved to None from a failed lookup; refactoring call sites to pass the api name positionally where it got dropped.
Related errors
- Data type not supported for metadata extraction.
- device-id: {device_id} not found
- create device path: {folder_path} failed
- api_name: {api_name} not found
- Environment has not been reset yet
AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14).
Data as JSON: /api/errors/380b2527a4c0282d.
Report an issue: GitHub.