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

  1. Check the error message: it enumerates valid types — switch to one of them
  2. Fix typos in tooling.type
  3. 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

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


AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27). Data as JSON: /api/errors/69666401de63773d. Report an issue: GitHub.