OpenBMB/ChatDev · error · ConfigError
env must be a mapping
Error message
env must be a mapping
What it means
Raised when the stdio tooling config 'env' key exists but is not a mapping/dict. The env dict is normalized to str->str; any non-mapping (list, string, scalar) is rejected.
Source
Thrown at entity/configs/node/tooling.py:523
mapping = require_mapping(data, path)
command = require_str(mapping, "command", path)
args_raw = ensure_list(mapping.get("args"))
normalized_args: List[str] = []
for idx, arg in enumerate(args_raw):
arg_path = extend_path(path, f"args[{idx}]")
if not isinstance(arg, str):
raise ConfigError("args entries must be strings", arg_path)
normalized_args.append(arg)
cwd = optional_str(mapping, "cwd", path)
inherit_env = optional_bool(mapping, "inherit_env", path, default=True)
if inherit_env is None:
inherit_env = True
env_mapping = mapping.get("env")
if env_mapping is not None:
if not isinstance(env_mapping, Mapping):
raise ConfigError("env must be a mapping", extend_path(path, "env"))
env = {str(k): str(v) for k, v in env_mapping.items()}
else:
env = {}
timeout_value = mapping.get("startup_timeout", 10.0)
if timeout_value is None:
startup_timeout = 10.0
elif isinstance(timeout_value, (int, float)):
startup_timeout = float(timeout_value)
else:
raise ConfigError("startup_timeout must be numeric", extend_path(path, "startup_timeout"))
wait_for_log = optional_str(mapping, "wait_for_log", path)
cache_ttl_value = mapping.get("cache_ttl", 0.0)
if cache_ttl_value is None:
cache_ttl = 0.0
elif isinstance(cache_ttl_value, (int, float)):
cache_ttl = float(cache_ttl_value)View on GitHub (pinned to 4fb2db0ea9)
Solutions
- Convert env to a mapping: env: {FOO: bar, BAZ: qux}
- If your source is shell-style assignments, parse them into a dict first (dict(x.split('=',1) for x in pairs))
- Remove env entirely to inherit/process-default to {}
Example fix
# before env: - FOO=bar # after env: FOO: bar
Defensive patterns
Strategy: type-guard
Validate before calling
env = cfg.get("env")
assert env is None or isinstance(env, dict) Type guard
from collections.abc import Mapping
def valid_env(v) -> bool:
return v is None or isinstance(v, Mapping) Try / catch
except ConfigError as e:
if "env must be a mapping" in str(e):
cfg["env"] = dict(x.split("=", 1) for x in cfg["env"]) # if list of K=V Prevention
- Store env as a YAML mapping, never a list of assignments
- Convert docker-style -e K=V lists to dicts before parsing
When it happens
Trigger: env: ["FOO=bar"] (list of assignments) instead of env: {FOO: bar}; env: "FOO=bar" as a plain string; YAML indentation making env a list.
Common situations: Copying docker-run style -e FOO=bar syntax into the config; shell-style env strings not converted to dicts.
Related errors
- args entries must be strings
- startup_timeout must be numeric
- tooling must be a list
- cache_ttl must be numeric
- tool_sources must be a list of strings
AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27).
Data as JSON: /api/errors/58dc3c817ed31090.
Report an issue: GitHub.