Fix: verify the LiteLLM database schema, repair it, and fail loudly
IMPLEMENTATION RULES: Before implementing this plan, read and follow:
- WORKFLOW.md - The implementation process
- PLANS.md - Plan structure and best practices
Status: Completed
Goal: uis deploy litellm must never report success when the database
schema was not created.
Investigation: INVESTIGATE-service-litellm-install-reliability.md
Priority: High
Last Updated: 2026-08-06
Completed: 2026-08-06
Problem
On a clean install the chart's migration Job fails with P1000 and exits
Completed anyway. The playbook never checks the schema, so the deploy reports
✅ SUCCESS with an empty database. The proxy appears healthy because models are
served from the ConfigMap, but virtual keys, spend tracking and budgets fail
silently. See findings F2–F4 in the investigation.
Solution
Add a verification block at the end of 210-setup-litellm.yml that:
- counts tables in the
litellmschema, - runs
prisma migrate deployinside the pod if the schema is missing, - restarts the deployment and waits for it to serve,
- fails the play if the schema is still absent.
Deliberately not attempting to fix the credentials — they were proven correct (F3). This detects and repairs an upstream failure whose root cause is not yet established.
Phase 1: Verification and repair — ✅ DONE
Tasks
- 1.1 Add task
20a— read the LiteLLM DB password fromurbalurba-secretsin theainamespace (no_log: true) - 1.2 Add task
20b— count tables viakubectl execinto thepostgresqlpod's first container (which carriespsql); pass the password through the taskenvironmentrather than the command line - 1.3 Add task
20c— display the table count - 1.4 Add task
20d— when fewer than 50 tables, locatelitellm_proxy_extras/schema.prismain the pod and runprisma migrate deploy - 1.5 Add task
20e— re-count after repair - 1.6 Add task
20f— restart the deployment so it picks up the schema - 1.7 Add task
20g—ansible.builtin.failwith an actionable message if the schema is still missing
Validation
psql -d litellm -c "select count(*) from information_schema.tables
where table_schema='public'" # -> 69+
Phase 2: Readiness — ✅ DONE
Discovered during Phase 1 validation: the play returned while the restarted pod
was still starting, so an immediate /v1/models query returned an empty list
(finding F5).
Tasks
- 2.1 Add task
20f2—kubectl rollout status --timeout=240safter the restart - 2.2 Add task
20f3— poll/v1/modelsuntil it answers200or401(retries: 20, delay: 6)
Validation
Five consecutive clean cycles report 5 models rather than 0.
Acceptance Criteria
- A clean install (database and role dropped) produces a populated schema
- The play fails, rather than printing SUCCESS, when the schema cannot be created
-
/v1/modelsanswers before the play returns - Virtual key generation works after install
- Repeatable across multiple clean cycles
Verification performed
Five full teardown → install cycles, each starting from
drop database litellm; drop role litellm:
| schema | serving-pod auth errors | models | completion | |
|---|---|---|---|---|
| run 1 | 69 tables ✅ | 0 | 5 | 'CLEAN' |
| run 2 | 69 tables ✅ | 0 | 5 | 'CLEAN' |
| run 3 | 77 tables ✅ | 0 | 5 | 'CLEAN' |
| run 4 | 69 tables ✅ | 0 | 5 | 'CLEAN' |
| run 5 | 77 tables ✅ | 0 | 5 | 'CLEAN' |
Before the fix the same procedure produced 0 tables with failed=0.
The upstream migration Job still logs P1000 on some runs (4 occurrences in two
of the five cycles, 0 in the others). Task 20d repairs it; the serving pod
has zero auth errors in all runs. Table counts differ (69 vs 77) depending on
whether the upstream Job succeeded before the repair ran — both are complete
schemas.
Implementation Notes
- The
postgresqlshim's first container ispostgres:18and carriespsql, which is what makes the table count possible without adding an image. - The password is passed via the task
environment:(PGPW), never as a command-line argument, so it does not appear in process listings. - The 50-table threshold distinguishes "no schema" from "complete schema" (69+) without being brittle about the exact count, which grows with each upstream migration.
Files to Modify
ansible/playbooks/210-setup-litellm.yml