{"record":{"id":"391c7f6f74834666","repo":"bytedance/deer-flow","slug":"model-model-name-not-found","errorCode":null,"errorMessage":"Model '{model_name}' not found","messagePattern":"Model '(.+?)' not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"warning","filePath":"backend/app/gateway/routers/models.py","lineNumber":169,"sourceCode":"    Raises:\n        HTTPException: 404 if model not found; 403 if the caller's role may not\n        ``use`` the model (only when ``authorization.enabled`` is true). A\n        provider resolution error yields 403 (fail-closed) or allows the request\n        (fail-open), mirroring ``list_models``'s provider-error semantics.\n\n    Example Response:\n        ```json\n        {\n            \"name\": \"gpt-4\",\n            \"display_name\": \"GPT-4\",\n            \"description\": \"OpenAI GPT-4 model\",\n            \"supports_thinking\": false\n        }\n        ```\n    \"\"\"\n    model = config.get_model_config(model_name)\n    if model is None:\n        raise HTTPException(status_code=404, detail=f\"Model '{model_name}' not found\")\n\n    # Phase 3: enforce model:use authorization (deny → 403, not 404, since the\n    # model exists but the role lacks permission to use it).\n    fail_closed = config.authorization.fail_closed\n    user = await get_optional_user_from_request(request)\n    if user is not None:\n        try:\n            provider, principal = resolve_model_authorization(user, is_internal=_is_internal_caller(request, user))\n        except _AuthorizationUnavailable:\n            if fail_closed:\n                raise HTTPException(status_code=403, detail=f\"Model '{model_name}' is not available for your role\")\n        else:\n            if provider is not None and principal is not None:\n                try:\n                    decision = provider.authorize(AuthzRequest(principal=principal, resource=\"model\", action=\"use\", target=model_name))\n                    if not isinstance(decision, AuthzDecision):\n                        raise TypeError(\"AuthorizationProvider.authorize must return AuthzDecision\")\n                    allowed = decision.allow","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/models.py#L151-L187","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Call GET /api/models to list configured model names and use one of those exactly.","Add or fix the model entry under the models section of config.yaml at the repo root, then reload config.","If you expected the model to exist, diff config.yaml against config.example.yaml for renames or missing entries."],"exampleFix":"# config.yaml — before: model key is \"gpt-4o\"\nmodels:\n  gpt-4o:\n    ... # GET /api/models/gpt4 -> 404\n# after: request the exact key\nmodels:\n  gpt-4o:\n    ...\n# GET /api/models/gpt-4o -> 200","handlingStrategy":"validation","validationCode":"models = requests.get(f\"{BASE}/api/models\").json()\nvalid_names = {m[\"name\"] for m in models}\nassert model_name in valid_names, f\"{model_name} not configured; valid: {sorted(valid_names)}\"","typeGuard":"def is_configured_model(name: str, catalog: list[dict]) -> bool:\n    return any(m.get(\"name\") == name for m in catalog)","tryCatchPattern":"resp = requests.get(f\"{BASE}/api/models/{model_name}\")\nif resp.status_code == 404:\n    model_name = pick_from_listed_models()  # recover by re-selecting\nelse:\n    resp.raise_for_status()","preventionTips":["Populate model pickers from GET /api/models, never hardcode names.","Keep config.yaml's models section in sync when renaming or removing entries.","Run make doctor after config edits to catch schema/name mistakes."],"tags":["models","config","http-404"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}