{"record":{"id":"f6a1e4dd1f16ff23","repo":"OpenBMB/ChatDev","slug":"model-name-must-be-a-non-empty-string","errorCode":null,"errorMessage":"model.name must be a non-empty string","messagePattern":"model\\.name must be a non-empty string","errorType":"validation","errorClass":"ConfigError","httpStatus":null,"severity":"error","filePath":"entity/configs/node/agent.py","lineNumber":350,"sourceCode":"    tooling: List[ToolingConfig] = field(default_factory=list)\n    thinking: ThinkingConfig | None = None\n    memories: List[MemoryAttachmentConfig] = field(default_factory=list)\n    skills: AgentSkillsConfig | None = None\n\n    # Runtime attributes (attached dynamically)\n    token_tracker: Any | None = field(default=None, init=False, repr=False)\n    node_id: str | None = field(default=None, init=False, repr=False)\n\n    @classmethod\n    def from_dict(cls, data: Mapping[str, Any], *, path: str) -> \"AgentConfig\":\n        mapping = require_mapping(data, path)\n        provider = require_str(mapping, \"provider\", path)\n        base_url = optional_str(mapping, \"base_url\", path)\n        name_value = mapping.get(\"name\")\n        if isinstance(name_value, str) and name_value.strip():\n            model_name = name_value.strip()\n        else:\n            raise ConfigError(\"model.name must be a non-empty string\", extend_path(path, \"name\"))\n\n        role = optional_str(mapping, \"role\", path)\n        api_key = optional_str(mapping, \"api_key\", path)\n        params = optional_dict(mapping, \"params\", path) or {}\n        raw_input_mode = optional_str(mapping, \"input_mode\", path)\n        input_mode = AgentInputMode.MESSAGES\n        if raw_input_mode:\n            try:\n                input_mode = AgentInputMode(raw_input_mode.strip().lower())\n            except ValueError as exc:\n                raise ConfigError(\n                    \"model.input_mode must be 'prompt' or 'messages'\",\n                    extend_path(path, \"input_mode\"),\n                ) from exc\n\n        tooling_cfg: List[ToolingConfig] = []\n        if \"tooling\" in mapping and mapping[\"tooling\"] is not None:\n            raw_tooling = mapping[\"tooling\"]","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/entity/configs/node/agent.py#L332-L368","documentation":"Raised when parsing an agent node config: the 'name' field under the model mapping is missing, None, not a string, or a blank/whitespace-only string. The library requires a model identifier (e.g. 'gpt-4o', 'claude-3-5-sonnet') to construct the LLM client. The path in the ConfigError points at the offending 'name' key.","triggerScenarios":"Calling AgentNodeConfig/ModelConfig.from_dict (or loading a serialized agent node) with a model dict that omits 'name', sets it to null, uses a non-string value like 123, or passes an empty/whitespace string ''.","commonSituations":"YAML/JSON agent definitions where the model name was commented out or renamed; template placeholders like '' left unfilled; name supplied as a number (e.g. name: 4 thinking it's a version) and silently coerced elsewhere.","solutions":["Add a non-empty 'name' string to the model mapping, e.g. \"name\": \"gpt-4o\"","Strip surrounding whitespace only if the value is genuinely present; ensure it is a str, not null/int","If the name comes from an env var, default it: os.environ.get('MODEL_NAME') or fail fast with a clear message","Check the error's path field to locate which node/model in a nested config failed"],"exampleFix":"// before\n{\"model\": {\"provider\": \"openai\", \"name\": \"\"}}\n// after\n{\"model\": {\"provider\": \"openai\", \"name\": \"gpt-4o\"}}","handlingStrategy":"validation","validationCode":"def check_model_name(cfg: dict) -> None:\n    name = cfg.get('model', {}).get('name')\n    if not isinstance(name, str) or not name.strip():\n        raise ValueError('model.name missing/blank')","typeGuard":"def has_valid_model_name(cfg: dict) -> bool:\n    n = cfg.get('model', {}).get('name')\n    return isinstance(n, str) and bool(n.strip())","tryCatchPattern":"try:\n    cfg = ModelConfig.from_dict(data, path='agent')\nexcept ConfigError as e:\n    if 'model.name' in e.path:\n        name = input('model name: ').strip() or DEFAULT_MODEL\n        data['model']['name'] = name\n        cfg = ModelConfig.from_dict(data, path='agent')\n    else:\n        raise","preventionTips":["Default model names from a constants module instead of literals scattered in configs","Assert required keys before from_dict when configs are user-authored","Log the ConfigError path — it names the exact failing key"],"tags":["config","agent","model","validation","python"],"backgroundTag":"schema-validation-failed","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}