2.2 KiB
LiteLLM DB Migration Pitfall — Encrypted Models Don't Survive pg_dump
Date: Jul 13, 2026
Root cause: LiteLLM encrypts model parameters (api_key, model name, provider) in LiteLLM_ProxyModelTable using the LITELLM_SALT_KEY. A pg_dump + pg_restore to a new server will list the models in /v1/models but completions fail with "Invalid model name passed."
Symptom: Same Docker image (v1.84.0), same SALT_KEY, same DB dump. Models appear in the listing but every completion returns 400: Invalid model name passed in model=X. Call /v1/models to view available models for your key.
Why: The encryption uses not just SALT_KEY but also some per-installation factor (possibly container hostname, Docker network IP, or a runtime-generated nonce) that differs between hosts. Identical SALT_KEY, identical DB, identical image — still can't decrypt.
Fix: Do NOT rely on DB migration for models. Instead:
- Export the list of model names from the old box
- Recreate each model fresh on the new box via the
/model/newendpoint - Test each model with a completion
# List models on old box
curl -s https://admin-ai.itpropartner.com/v1/models -H "Authorization: Bearer $KEY" | jq -r '.data[].id' > models.txt
# Recreate on new box
while read model; do
curl -s http://127.0.0.1:4000/model/new -X POST \
-H "Authorization: Bearer $MASTER_KEY" \
-H "Content-Type: application/json" \
-d "{\"model_name\":\"$model\",\"litellm_params\":{\"model\":\"$model\",\"custom_llm_provider\":\"openai\",\"api_base\":\"https://admin-ai.itpropartner.com/v1\",\"api_key\":\"$ADMIN_AI_KEY\"}}"
done < models.txt
Alternative: If migrating TO a self-hosted LiteLLM that replaces the old admin-ai proxy, configure models to use OpenRouter directly instead of routing through admin-ai. This avoids the proxy-in-a-loop problem post-DNS-cutover.
Credentials table survives — The LiteLLM_CredentialsTable decrypts fine after migration. Only LiteLLM_ProxyModelTable entries fail.
Post-migration config.yaml requirement: The new LiteLLM needs a config.yaml with database_url, store_model_in_db: true, and enforce_database: true. Without it, models created via API are lost on restart.