bytedance/deer-flow · error · HTTPException

Unknown model '{model}'. Use a model name defined under `mod

Error message

Unknown model '{model}'. Use a model name defined under `models:` in config.yaml.

What it means

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.

Source

Thrown at backend/app/gateway/routers/agents.py:135

    Mirrors the ``update_agent`` harness tool: without this, an unknown model
    silently falls back to the default at runtime and the user sees confusing
    repeated warnings on every later turn instead of an actionable error here.
    ``None``/empty means "use the global default" and is always allowed.

    Best-effort: if the app config cannot be loaded (e.g. no ``config.yaml`` on
    disk in a bare/test deployment), skip the check rather than failing the
    write — the runtime still falls back to the default for an unknown model.
    """
    if not model:
        return
    try:
        app_config = get_app_config()
    except Exception:
        logger.warning("Could not load app config to validate agent model %r; skipping model existence check.", model)
        return
    if app_config.get_model_config(model) is None:
        raise HTTPException(status_code=422, detail=f"Unknown model '{model}'. Use a model name defined under `models:` in config.yaml.")


def _merge_model_settings_update(value: AgentModelSettings, existing: AgentModelSettings | None) -> dict:
    """Merge an explicit ``model_settings`` update with existing sub-fields.

    The top-level ``model_settings`` key is optional in update requests:
    omitted means "preserve the current block", while explicit ``null`` means
    "clear the block". Inside the block, omitted sub-fields should behave the
    same way. This lets API callers update only ``temperature`` without
    accidentally clearing an existing ``max_tokens``.
    """
    merged = existing.model_dump(exclude_none=True) if existing is not None else {}
    for field in value.model_fields_set:
        field_value = getattr(value, field)
        if field_value is None:
            merged.pop(field, None)
        else:
            merged[field] = field_value

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Open config.yaml, list the keys under `models:`, and use one of those exact names
  2. Add a `models:` entry for the desired model if it is legitimately available
  3. Pass `model: null`/omit the field to inherit the global default
  4. Expose the configured model list to the frontend so pickers only offer valid names

Example fix

# before
PUT /agents/my-agent { "model": "gpt-4o" }  # not in models: -> 422
# after
PUT /agents/my-agent { "model": "deepseek-chat" }  # exact key from config.yaml models:
Defensive patterns

Strategy: validation

Validate before calling

const knownModels = new Set(await fetchConfiguredModels()); // keys of models: in config.yaml
if (body.model && !knownModels.has(body.model)) {
  throw new Error(`model ${body.model} not in config.yaml models:`);
}

Type guard

const isKnownModel = (m: string | null | undefined, known: Set<string>) =>
  m == null || m === '' || known.has(m);

Try / catch

try { await api.updateAgent(name, body); }
catch (e) {
  if (e.status === 422 && /Unknown model/.test(e.detail)) { body.model = null; return api.updateAgent(name, body); }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/6bb182f7373cfa02. Report an issue: GitHub.