fix(proxy): skip prisma-dependent hooks when no database is attached - #36273
Merged
mateo-berri merged 1 commit intoAug 9, 2026
Merged
Conversation
Contributor
Greptile SummaryThis PR prevents database-dependent enterprise hooks from being registered when no Prisma client is available and rejects storage-backend uploads requiring managed-file routing before uploading.
Confidence Score: 5/5The PR appears safe to merge with no actionable correctness or security issues identified. The changed registration logic matches the affected hook signatures, preserves database-backed behavior, and fails target-model storage requests before external upload when required persistence is unavailable.
|
| Filename | Overview |
|---|---|
| litellm/proxy/utils.py | Adds startup-time filtering for hooks that explicitly require an unavailable Prisma client; the affected production hook signatures are correctly detected. |
| litellm/proxy/openai_files_endpoints/storage_backend_service.py | Adds a pre-upload managed-files capability check for target-model routing and returns a clear client error when unavailable. |
| tests/test_litellm/proxy/openai_files_endpoint/test_storage_backend_service.py | Covers rejection before upload, hook-free uploads without target models, and successful managed-file metadata storage. |
| tests/test_litellm/proxy/utils/proxy_logging/test_lifecycle.py | Adds lifecycle tests proving Prisma-dependent hooks are skipped without a database and registered when a client exists. |
Reviews (1): Last reviewed commit: "fix(proxy): skip prisma-dependent hooks ..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
tin-berri
approved these changes
Aug 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TLDR
Problem this solves:
'NoneType' object has no attribute 'db'How it solves it:
target_model_nameswithout a database fail fast with a 400User Flow
Before: a batch create through a proxy running without a database spends real money and then reports failure
DATABASE_URLpurpose=batch,custom_llm_provider=vertex_ai) and gets back an id likegs://<bucket>/litellm-vertex-files/publishers/google/models/gemini-3.6-flash/<uuid>"custom_llm_provider": "vertex_ai", and get HTTP 500 with{"error":{"message":"'NoneType' object has no attribute 'db'", ...}}After: the same walk returns the batch object and the batch lifecycle completes without a database
"status": "validating""status": "completed"and the output sits at the returned output file pathRelevant issues
Resolves #36265
Linear ticket
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaito re-request a review after pushing changes)Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
Screenshots / Proof of Fix
Live e2e proof, no mocks, real Vertex AI spend. Both legs boot a DB-less proxy from its own clean worktree: no
DATABASE_URLanywhere (the leg.envcarries only GCS settings,grep -c DATABASE_URL .envprints 0, and the boot log printsprisma_client: None), same config (gemini-3.6-flash, projectvertex-check-481318, locationglobal), same flow. Only the commit the proxy boots from differsBefore leg, merge base b6e3ff6: 500 after the provider job already started
The upload succeeds:
then the batch create 500s and the client never sees the batch id:
The proxy log shows the provider call had already succeeded,
LiteLLMBatch(id='1667570736853680128', ..., status='validating'), before the hook crashed:and querying Vertex directly confirms the orphaned job exists and bills:
After leg, PR head 855c49d: 200 and pollable to completed
The startup log shows the fix at work, and the pre-fix error string appears zero times in the whole log:
Same upload, then the same batch create now returns the batch object:
and polling reaches a terminal state in about 3.5 minutes (validating -> in_progress -> completed):
Type
🐛 Bug Fix
Changes
_add_proxy_hooks(litellm/proxy/utils.py) instantiated every registered hook, passing the module-globalprisma_clientinto any constructor that asks for it, and registered the result even when that global wasNone. Two enterprise hooks have such constructors,managed_filesandmanaged_vector_stores, and the managed-files post-success handler writes every batch and fine-tuning create to the database unconditionally, so on DB-less proxies the write raisedAttributeErrorafter the provider had already accepted the job. The fix skips construction and registration of a hook whose constructor requiresprisma_clientwhile none is configured, with a debug log naming the skipped hookStartup ordering makes the skip safe for DB-backed deployments: the lifespan sets the prisma client (
proxy_server.py:1002) before hook registration runs (_initialize_startup_loggingatproxy_server.py:1068->startup_event->_init_litellm_callbacks, the only path into_add_proxy_hooks), and the function re-imports the global at call time. Every consumer ofget_proxy_hook("managed_files")and ofget_proxy_hook("managed_vector_stores")already handlesNone, since that is what non-enterprise installs return todayOne consumer needed an explicit decision:
POST /v1/fileswithtarget_model_namesplus a storage backend previously crashed the same way on DB-less proxies after uploading the file. With the hook absent it would have silently returned a file that cannot do target-model routing, soupload_file_to_storage_backendnow rejectstarget_model_nameswith a 400 naming the database requirement before uploading anything. That also turns the pre-existing silent skip on enterprise-absent deployments into the same explicit 400Tests:
test_lifecycle.pygains regression tests that aprisma_client-requiring hook is skipped (mapping and callbacks) without a database and registered with one, and the skip test fails on the unfixed code. A newtest_storage_backend_service.pypins the 400 firing before upload, the no-target_model_namespath staying hook-free, and the with-hook path storing the unified idFinal Attestation