bytedance/deer-flow · warning · HTTPException

Model '{model_name}' not found

Error message

Model '{model_name}' not found

What it means

Raised as HTTP 404 by GET /api/models/{model_name} when config.get_model_config(model_name) returns None — the requested model name is not present in the resolved configuration's model list. Authorization is checked only after existence, so this fires before any role-based filtering.

Source

Thrown at backend/app/gateway/routers/models.py:169

    Raises:
        HTTPException: 404 if model not found; 403 if the caller's role may not
        ``use`` the model (only when ``authorization.enabled`` is true). A
        provider resolution error yields 403 (fail-closed) or allows the request
        (fail-open), mirroring ``list_models``'s provider-error semantics.

    Example Response:
        ```json
        {
            "name": "gpt-4",
            "display_name": "GPT-4",
            "description": "OpenAI GPT-4 model",
            "supports_thinking": false
        }
        ```
    """
    model = config.get_model_config(model_name)
    if model is None:
        raise HTTPException(status_code=404, detail=f"Model '{model_name}' not found")

    # Phase 3: enforce model:use authorization (deny → 403, not 404, since the
    # model exists but the role lacks permission to use it).
    fail_closed = config.authorization.fail_closed
    user = await get_optional_user_from_request(request)
    if user is not None:
        try:
            provider, principal = resolve_model_authorization(user, is_internal=_is_internal_caller(request, user))
        except _AuthorizationUnavailable:
            if fail_closed:
                raise HTTPException(status_code=403, detail=f"Model '{model_name}' is not available for your role")
        else:
            if provider is not None and principal is not None:
                try:
                    decision = provider.authorize(AuthzRequest(principal=principal, resource="model", action="use", target=model_name))
                    if not isinstance(decision, AuthzDecision):
                        raise TypeError("AuthorizationProvider.authorize must return AuthzDecision")
                    allowed = decision.allow

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Call GET /api/models to list configured model names and use one of those exactly.
  2. Add or fix the model entry under the models section of config.yaml at the repo root, then reload config.
  3. If you expected the model to exist, diff config.yaml against config.example.yaml for renames or missing entries.

Example fix

# config.yaml — before: model key is "gpt-4o"
models:
  gpt-4o:
    ... # GET /api/models/gpt4 -> 404
# after: request the exact key
models:
  gpt-4o:
    ...
# GET /api/models/gpt-4o -> 200
Defensive patterns

Strategy: validation

Validate before calling

models = requests.get(f"{BASE}/api/models").json()
valid_names = {m["name"] for m in models}
assert model_name in valid_names, f"{model_name} not configured; valid: {sorted(valid_names)}"

Type guard

def is_configured_model(name: str, catalog: list[dict]) -> bool:
    return any(m.get("name") == name for m in catalog)

Try / catch

resp = requests.get(f"{BASE}/api/models/{model_name}")
if resp.status_code == 404:
    model_name = pick_from_listed_models()  # recover by re-selecting
else:
    resp.raise_for_status()

Prevention

When it happens

Trigger: GET /api/models/{model_name} with a name absent from config.yaml's models section: typo ('gpt4' vs 'gpt-4'), model removed from config, or config.yaml not yet populated from config.example.yaml.

Common situations: Frontend or script hardcodes a model name that the deployment's config.yaml does not define; after upgrading, model keys renamed; default config copied but models left as examples.

Related errors


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