bytedance/deer-flow · error · HTTPException

Model {model_name!r} is not in the configured model allowlis

Error message

Model {model_name!r} is not in the configured model allowlist

What it means

HTTP 400 raised when the caller supplies context.model_name and the Gateway cannot resolve it via app_config.get_model_config(model_name). The Gateway enforces a model allowlist at request admission: any model_name not present in config.yaml's models list is rejected before the run starts, even though the lead agent itself would silently fall back to the default model.

Source

Thrown at backend/app/gateway/services.py:1097

    stream_modes = normalize_stream_modes(body.stream_mode)
    bridge = get_stream_bridge(request)
    run_mgr = get_run_manager(request)
    run_ctx = get_run_context(request)

    disconnect = DisconnectMode.cancel if body.on_disconnect == "cancel" else DisconnectMode.continue_

    body_context = getattr(body, "context", None) or {}
    model_name = body_context.get("model_name")
    # Coerce non-string model_name values to str before truncation.
    if model_name is not None and not isinstance(model_name, str):
        model_name = str(model_name)

    # Validate model against the allowlist when a model_name is provided.
    if model_name:
        app_config = get_app_config()
        resolved = app_config.get_model_config(model_name)
        if resolved is None:
            raise HTTPException(
                status_code=400,
                detail=f"Model {model_name!r} is not in the configured model allowlist",
            )

    owner_user_id = get_trusted_internal_owner_user_id(request)
    # Stateless run endpoints carry thread_id in the request *body*, so the
    # @require_permission(owner_check=True) decorator -- which resolves ownership
    # from the path param -- cannot protect them. Enforce thread ownership here,
    # before any run is created, so one user cannot start runs on (or read /wait
    # checkpoint state from) another user's thread. Missing rows (auto-created
    # temp threads) and NULL-owner rows (shared / pre-auth data) stay accessible
    # via check_access; only a thread already owned by another user is rejected
    # with 404, matching thread_runs.py's anti-enumeration behaviour. Internal
    # channel runs act on behalf of the connection owner carried in
    # X-DeerFlow-Owner-User-Id, so they are scoped to that owner instead of
    # bypassing the check -- a leaked internal token must not grant cross-user
    # thread access.
    user = getattr(request.state, "user", None)

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Compare the sent model_name against GET /api/models (or config.yaml models:) and use an exact configured name.
  2. Fix typos/whitespace/case in the model_name value the client sends.
  3. If the model should exist, add its full entry to config.yaml under models and restart the Gateway.
  4. Omit context.model_name entirely to let the server use its default model.

Example fix

# config.yaml
models:
  - name: gpt-4o        # client must send exactly "gpt-4o"
    provider: openai
    ...
Defensive patterns

Strategy: validation

Validate before calling

const models = await api.listModels(); // names from config.yaml
const allowed = new Set(models.map(m => m.name));
if (body.context?.model_name && !allowed.has(body.context.model_name)) {
  delete body.context.model_name; // or pick allowed names interactively
}

Type guard

const isConfiguredModel = (name, configured) => typeof name === 'string' && configured.some(m => m.name === name);

Try / catch

try { await api.createRun(threadId, body); } catch (e) { if (e.status === 400 && /allowlist/.test(e.detail)) { refresh model list, correct model_name, retry once; } throw e; }

Prevention

When it happens

Trigger: POST a run with body.context.model_name set to a name that is not a key in config.yaml models (typo, removed model, env-specific name), or a non-string value coerced to str (e.g. 42 -> '42').

Common situations: Frontend hardcodes a model name from another environment (dev vs prod config.yaml differ); a model was renamed or deleted from config.yaml; the user picked a model in the UI that the backend config never defined; typo like 'gpt-4o ' with whitespace.

Related errors


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