{"record":{"id":"cab13ca9c4c4cf28","repo":"BerriAI/litellm","slug":"e-cab13c","errorCode":null,"errorMessage":"{e}","messagePattern":"\\{e\\}","errorType":"exception","errorClass":"UnauthorizedError","httpStatus":401,"severity":"error","filePath":"litellm/proxy/client/model_groups.py","lineNumber":61,"sourceCode":"        Raises:\n            UnauthorizedError: If the request fails with a 401 status code\n            requests.exceptions.RequestException: If the request fails with any other error\n        \"\"\"\n        url: Final = f\"{self._base_url}/model_group/info\"\n        request: Final = requests.Request(\"GET\", url, headers=self._get_headers())\n\n        if return_request:\n            return request\n\n        # Prepare and send the request\n        session: Final = requests.Session()\n        try:\n            response: Final = session.send(request.prepare())\n            response.raise_for_status()\n            return response.json()[\"data\"]\n        except requests.exceptions.HTTPError as e:\n            if e.response.status_code == 401:\n                raise UnauthorizedError(e)\n            raise\n","sourceCodeStart":43,"sourceCodeEnd":63,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/client/model_groups.py#L43-L63","documentation":"Raised by ModelGroupsManagementClient.info() when GET {base_url}/model_group/info returns HTTP 401, mapped to UnauthorizedError (redacted message; original HTTPError on .orig_exception; any other non-2xx re-raises as plain requests HTTPError). On success the method returns response.json()[\"data\"], so authentication is the only failure mode it translates into a library-specific exception.","triggerScenarios":"Calling model_groups.info() with no api_key on an auth-enforcing proxy; using a virtual/end-user key for what is a management endpoint; a rotated or revoked admin key.","commonSituations":"Monitoring tools scraping model-group spend/tps data with stale credentials; proxy upgraded and master key changed; script moved between environments without updating the key.","solutions":["Provide the admin key: ModelGroupsManagementClient(base_url, api_key=os.environ[\"LITELLM_MASTER_KEY\"]).info()","Validate the key with curl -H \"Authorization: Bearer $KEY\" $BASE_URL/model_group/info","Refresh credentials after rotation and confirm base_url points at the right proxy"],"exampleFix":"# before\nmg = ModelGroupsManagementClient(\"http://localhost:4000\")\nmg.info()  # UnauthorizedError\n\n# after\nimport os\nmg = ModelGroupsManagementClient(\"http://localhost:4000\", api_key=os.environ[\"LITELLM_MASTER_KEY\"])\nmg.info()","handlingStrategy":"try-catch","validationCode":"import requests\n\ndef model_groups_readable(base_url: str, api_key: str | None) -> bool:\n    if not api_key:\n        return False\n    r = requests.get(\n        f\"{base_url.rstrip('/')}/model_group/info\",\n        headers={\"Authorization\": f\"Bearer {api_key}\"},\n        timeout=10,\n    )\n    return r.status_code != 401","typeGuard":null,"tryCatchPattern":"from litellm.proxy.client.exceptions import UnauthorizedError\nimport requests\n\ntry:\n    groups = model_groups.info()\nexcept UnauthorizedError:\n    rotate_admin_key()  # 401 — credentials rejected\nexcept requests.exceptions.HTTPError as e:\n    log_and_surface(e.response)  # any other non-2xx","preventionTips":["Management endpoints need management credentials — keep a dedicated admin key for dashboards","Validate credentials once at startup instead of per scrape","Alert on 401 rates so silent key rotation is caught early"],"tags":["litellm","authentication","http-401","python","model-groups"],"backgroundTag":"http-401-unauthorized","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}