From 0c73928a6d89ab54c64e862edd58f90d9faa9cba Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Tue, 19 May 2026 22:26:52 -0700 Subject: [PATCH] ci(proxy-mgmt-behavior): await LiteLLM_VerificationTokenView creation in fixture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fourth CI run still failed because the proxy's lifespan kicks off ``prisma_client.check_view_exists()`` as a fire-and-forget background task — that task is what creates ``LiteLLM_VerificationTokenView``, the SQL view ``user_api_key_auth`` queries to resolve a token to its user_id / user_role / team. On a fresh Postgres (CI), the first test races the background task. The view doesn't exist when the first auth call runs, the resolver falls through to a degraded path that returns ``user_id=None``, and every matrix test that depends on the seeded actor's identity then fails confusingly with "Got user_id=X, Your ID=None" 403s. Locally the view persists across pytest runs so the race is invisible. Fix: await ``prisma_client.check_view_exists()`` explicitly inside the session ``proxy_app`` fixture, after the lifespan enters but before the fixture yields. Deterministic regardless of whether the underlying DB is fresh (CI) or warm (local). --- tests/proxy_behavior/management/conftest.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/proxy_behavior/management/conftest.py b/tests/proxy_behavior/management/conftest.py index 23f2e24e604..b87fc1aa0c6 100644 --- a/tests/proxy_behavior/management/conftest.py +++ b/tests/proxy_behavior/management/conftest.py @@ -54,6 +54,19 @@ async def proxy_app(): config_path = _write_minimal_proxy_config() await initialize(config=config_path) async with proxy_startup_event(app): + # The lifespan kicks off ``prisma_client.check_view_exists()`` as a + # fire-and-forget background task. That task creates the + # ``LiteLLM_VerificationTokenView`` SQL view used by ``user_api_key_auth`` + # to resolve a token to its user / role / team. On a fresh Postgres + # (CI), the first test races the task — the view doesn't exist yet, + # ``user_api_key_dict.user_id`` resolves to ``None``, and every authz + # check that depends on it fails confusingly. Locally the view already + # exists from prior runs, masking the race. Await it explicitly here + # so the suite is deterministic regardless of DB state. + from litellm.proxy import proxy_server as _proxy_server + + if _proxy_server.prisma_client is not None: + await _proxy_server.prisma_client.check_view_exists() yield app