{"record":{"id":"163cd77cb87dbcd6","repo":"BerriAI/litellm","slug":"organization-doesn-t-exist-in-db-organization-or","errorCode":null,"errorMessage":"Organization doesn't exist in db. Organization={org_id}. Create organization via `/organization/new` call.","messagePattern":"Organization doesn't exist in db\\. Organization=(.+?)\\. Create organization via `/organization/new` call\\.","errorType":"exception","errorClass":"OrganizationNotFoundError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/auth/auth_checks.py","lineNumber":3324,"sourceCode":"    if deserialized_org is not None:\n        return deserialized_org\n    # else, check db\n    try:\n        query_kwargs: Final[dict[str, Mapping[str, object]]] = {\"where\": {\"organization_id\": org_id}}\n        if include_budget_table:\n            query_kwargs[\"include\"] = {\"litellm_budget_table\": True}\n\n        response: Final = await _model_dump_table(OrganizationRepository(prisma_client)).find_unique(**query_kwargs)\n    except Exception:\n        # An operational failure (DB down, timeout, cache fault) is NOT the same fact as a confirmed\n        # missing row, and relabelling it as \"doesn't exist\" made every caller unable to tell them\n        # apart — a caller that treats absence as \"this org places no restriction\" then drops a real\n        # org ceiling during an outage. Propagate the real error; callers that already catch\n        # Exception are unaffected.\n        raise\n\n    if response is None:\n        raise OrganizationNotFoundError(\n            f\"Organization doesn't exist in db. Organization={org_id}. Create organization via `/organization/new` call.\"\n        )\n\n    _org_obj: Final = LiteLLM_OrganizationTable.model_validate(response.model_dump())\n    # Cache the result\n    await user_api_key_cache.async_set_cache(\n        key=cache_key,\n        value=_org_obj,\n        model_type=LiteLLM_OrganizationTable,\n        ttl=DEFAULT_IN_MEMORY_TTL,\n    )\n\n    return _org_obj\n\n\nasync def _get_resources_from_access_groups(\n    access_group_ids: Sequence[str],\n    resource_field: Literal[\"access_model_names\", \"access_mcp_server_ids\", \"access_agent_ids\"],","sourceCodeStart":3306,"sourceCodeEnd":3342,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/auth/auth_checks.py#L3306-L3342","documentation":"OrganizationNotFoundError raised when the by-id organization query returns None: the row is confirmed absent from LiteLLM_OrganizationTable. Unlike the generic 500 wrapper, this exception deliberately distinguishes 'org really does not exist' from operational failures (which now propagate raw), so callers can treat absence as 'no org restriction' without swallowing DB outages. It subclasses Exception, so existing except Exception handlers keep working.","triggerScenarios":"A key/user/team references organization_id that has no row — e.g. the org was deleted after keys were issued, the id is a stale JWT claim, or a key was created with a mistyped organization_id.","commonSituations":"Org deletion without cleaning up member keys/users; environment mismatch (org exists in prod DB, request hits staging); copying key definitions between configs with hardcoded org ids.","solutions":["Create the organization via POST /organization/new and use the returned organization_id on keys/users","GET /organization/list to confirm the correct organization_id; update the key or user via /key/update or /user/update to point at an existing org","When deleting organizations, also detach or update keys/users/teams that reference the org id"],"exampleFix":"curl -X POST http://localhost:4000/organization/new \\\n  -H \"Authorization: Bearer $MASTER_KEY\" \\\n  -d '{\"organization_alias\": \"acme-corp\"}'\n# attach key to org\ncurl -X POST http://localhost:4000/key/update \\\n  -H \"Authorization: Bearer $MASTER_KEY\" \\\n  -d '{\"key\": \"sk-...\", \"organization_id\": \"org-returned-id\"}'","handlingStrategy":"type-guard","validationCode":"orgs = (await client.get(\"/organization/list\")).json()\nvalid_ids = {o[\"organization_id\"] for o in orgs}\nassert key_org_id in valid_ids, f\"organization {key_org_id} no longer exists\"","typeGuard":"from litellm.proxy.auth.auth_checks import OrganizationNotFoundError\n\ndef is_confirmed_missing(exc: Exception) -> bool:\n    \"\"\"True only for a confirmed-absent org, never for an outage.\"\"\"\n    return isinstance(exc, OrganizationNotFoundError)","tryCatchPattern":"from litellm.proxy.auth.auth_checks import OrganizationNotFoundError\n\ntry:\n    org = await get_org_object(org_id, prisma_client, cache)\nexcept OrganizationNotFoundError:\n    org = None  # confirmed absent: treat as 'no org restriction' safely\nexcept Exception:\n    raise      # operational failure: do NOT treat as absence","preventionTips":["Catch OrganizationNotFoundError specifically instead of bare Exception so DB outages are not mistaken for missing orgs","Cascade org deletion: detach keys/users/teams when deleting an organization"],"tags":["litellm","organization","not-found","authentication"],"backgroundTag":"resource-not-found","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}