OpenBMB/ChatDev · error · ConfigError
tooling.type must be one of {list(iter_tooling_type_registra
Error message
tooling.type must be one of {list(iter_tooling_type_registrations().keys())} What it means
ToolingConfig.from_dict dispatches on tooling.type via a registry; when the type string has no registered config class (RegistryError), it re-raises as ConfigError listing all valid types (e.g. http, stdio-style entries).
Source
Thrown at entity/configs/node/tooling.py:630
description="Configuration block validated by the chosen tool type (Python function list, MCP server settings, local command MCP launch, etc.).",
),
}
@classmethod
def child_routes(cls) -> Dict[ChildKey, type[BaseConfig]]:
return {
ChildKey(field="config", value=name): config_cls
for name, config_cls in iter_tooling_type_registrations().items()
}
@classmethod
def from_dict(cls, data: Mapping[str, Any], *, path: str) -> "ToolingConfig":
mapping = require_mapping(data, path)
tooling_type = require_str(mapping, "type", path)
try:
config_cls = get_tooling_type_config(tooling_type)
except RegistryError as exc:
raise ConfigError(
f"tooling.type must be one of {list(iter_tooling_type_registrations().keys())}",
extend_path(path, "type"),
) from exc
config_payload = mapping.get("config")
if config_payload is None:
raise ConfigError("tooling requires config block", extend_path(path, "config"))
config_obj = config_cls.from_dict(config_payload, path=extend_path(path, "config"))
prefix = optional_str(mapping, "prefix", path)
return cls(type=tooling_type, config=config_obj, prefix=prefix, path=path)
@classmethod
def field_specs(cls) -> Dict[str, ConfigFieldSpec]:
specs = super().field_specs()
type_spec = specs.get("type")
if type_spec:View on GitHub (pinned to 4fb2db0ea9)
Solutions
- Check the error message: it enumerates valid types — switch to one of them
- Fix typos in tooling.type
- For custom tooling, ensure the module registering the type is imported before from_dict runs
Example fix
# before
{"type": "stdioo", "config": {...}}
# after
{"type": "stdio", "config": {...}} Defensive patterns
Strategy: validation
Validate before calling
from wherever import iter_tooling_type_registrations valid = set(iter_tooling_type_registrations().keys()) assert data["tooling"]["type"] in valid
Type guard
def is_known_tooling_type(t: str) -> bool:
return t in iter_tooling_type_registrations() Try / catch
except ConfigError as e:
if "must be one of" in str(e):
show_valid_types(e) # message lists them; prompt user to pick Prevention
- Import plugin modules that register custom tooling types before loading configs
- Re-check valid type names after library upgrades
When it happens
Trigger: tooling.type: "http2", a typo like "htp", or a plugin type whose registration never ran (registry entry not imported).
Common situations: Upgrading versions that renamed/removed tooling types; custom tooling classes defined but never registered via the registration API; typos in hand-edited configs.
Related errors
- tooling must be a list
- unsupported memory store type '{store_type}'
- unsupported node type '{node_type}'
- 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/69666401de63773d.
Report an issue: GitHub.