{"record":{"id":"6bb182f7373cfa02","repo":"bytedance/deer-flow","slug":"unknown-model-model-use-a-model-name-defined","errorCode":null,"errorMessage":"Unknown model '{model}'. Use a model name defined under `models:` in config.yaml.","messagePattern":"Unknown model '(.+?)'\\. Use a model name defined under `models:` in config\\.yaml\\.","errorType":"http","errorClass":"HTTPException","httpStatus":422,"severity":"error","filePath":"backend/app/gateway/routers/agents.py","lineNumber":135,"sourceCode":"\n    Mirrors the ``update_agent`` harness tool: without this, an unknown model\n    silently falls back to the default at runtime and the user sees confusing\n    repeated warnings on every later turn instead of an actionable error here.\n    ``None``/empty means \"use the global default\" and is always allowed.\n\n    Best-effort: if the app config cannot be loaded (e.g. no ``config.yaml`` on\n    disk in a bare/test deployment), skip the check rather than failing the\n    write — the runtime still falls back to the default for an unknown model.\n    \"\"\"\n    if not model:\n        return\n    try:\n        app_config = get_app_config()\n    except Exception:\n        logger.warning(\"Could not load app config to validate agent model %r; skipping model existence check.\", model)\n        return\n    if app_config.get_model_config(model) is None:\n        raise HTTPException(status_code=422, detail=f\"Unknown model '{model}'. Use a model name defined under `models:` in config.yaml.\")\n\n\ndef _merge_model_settings_update(value: AgentModelSettings, existing: AgentModelSettings | None) -> dict:\n    \"\"\"Merge an explicit ``model_settings`` update with existing sub-fields.\n\n    The top-level ``model_settings`` key is optional in update requests:\n    omitted means \"preserve the current block\", while explicit ``null`` means\n    \"clear the block\". Inside the block, omitted sub-fields should behave the\n    same way. This lets API callers update only ``temperature`` without\n    accidentally clearing an existing ``max_tokens``.\n    \"\"\"\n    merged = existing.model_dump(exclude_none=True) if existing is not None else {}\n    for field in value.model_fields_set:\n        field_value = getattr(value, field)\n        if field_value is None:\n            merged.pop(field, None)\n        else:\n            merged[field] = field_value","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/agents.py#L117-L153","documentation":"422 from `_validate_model_exists`: the request's `model` field is not a key under `models:` in config.yaml. The check mirrors the harness `update_agent` tool so callers get an actionable error at write time instead of silent fallback plus repeated runtime warnings. It is best-effort: if app config cannot be loaded (bare/test deployment), the check is skipped.","triggerScenarios":"Creating/updating an agent with `model: 'gpt-4o'` when config.yaml only defines e.g. `deepseek-chat` and `qwen-max`; passing a model id from a different environment; typos in model profile names.","commonSituations":"Copying agent configs between deployments with different `models:` blocks; model profiles renamed in config while stored agent definitions keep the old name; frontend model pickers not synced with server config.","solutions":["Open config.yaml, list the keys under `models:`, and use one of those exact names","Add a `models:` entry for the desired model if it is legitimately available","Pass `model: null`/omit the field to inherit the global default","Expose the configured model list to the frontend so pickers only offer valid names"],"exampleFix":"# before\nPUT /agents/my-agent { \"model\": \"gpt-4o\" }  # not in models: -> 422\n# after\nPUT /agents/my-agent { \"model\": \"deepseek-chat\" }  # exact key from config.yaml models:","handlingStrategy":"validation","validationCode":"const knownModels = new Set(await fetchConfiguredModels()); // keys of models: in config.yaml\nif (body.model && !knownModels.has(body.model)) {\n  throw new Error(`model ${body.model} not in config.yaml models:`);\n}","typeGuard":"const isKnownModel = (m: string | null | undefined, known: Set<string>) =>\n  m == null || m === '' || known.has(m);","tryCatchPattern":"try { await api.updateAgent(name, body); }\ncatch (e) {\n  if (e.status === 422 && /Unknown model/.test(e.detail)) { body.model = null; return api.updateAgent(name, body); }\n  throw e;\n}","preventionTips":["Drive model pickers from the server's configured model list, never a hardcoded array","Omit the model field rather than sending a guessed default","Validate against config.yaml before importing agent definitions from another environment"],"tags":["validation","http-422","config","models","agents"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}