fix(managed_files): skip unparseable rows when listing managed files - #36021
Merged
mateo-berri merged 4 commits intoAug 7, 2026
Merged
Conversation
get_user_created_file_ids validated every row's file_object without a guard, so a single row failing OpenAIFileObject validation raised ValidationError and turned the whole GET /v1/files response into a 500. #35365 covered the null case only, leaving malformed or partial rows able to take the entire listing down. Rows now parse through a helper that returns None on failure and logs a warning, matching how list_user_batches already tolerates rows it cannot parse, so one bad row costs its own entry instead of the caller's whole listing. Null rows stay silent since the batch cost poller registers those legitimately. Refs #35361
Contributor
Greptile SummaryThis PR makes managed-file listing resilient to malformed persisted file objects while sanitizing validation warnings.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains, and the previously reported logging issue is addressed by excluding Pydantic input, URL, and context data while retaining schema-defined diagnostics.
|
| Filename | Overview |
|---|---|
| enterprise/litellm_enterprise/proxy/hooks/managed_files.py | Adds isolated parsing and sanitized warning behavior so malformed rows no longer fail the complete managed-file listing. |
| tests/test_litellm/enterprise/proxy/test_managed_files_hook.py | Adds focused regression tests confirming malformed rows are skipped and rejected filename values are omitted from warnings. |
Reviews (3): Last reviewed commit: "fix(managed_files): log sanitized valida..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
The skip warning interpolated the full pydantic ValidationError, whose string embeds input_value with the rejected row's contents. Managed-file rows carry a caller-supplied filename, so a malformed row copied that into operational logs. Log the error locations, types, and messages via errors() with input, url, and context excluded, keeping the field-level diagnostics without the values. Non-validation failures fall back to the exception type.
Contributor
Author
…laude/open-source-pr-merge-ven7h6 # Conflicts: # enterprise/litellm_enterprise/proxy/hooks/managed_files.py
yucheng-berri
approved these changes
Aug 6, 2026
Contributor
Author
|
|
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:
GET /v1/filesHow it solves it:
Noneon failurelist_user_batchesalready behavesRelevant issues
Follow-up to #35365, which fixed the null-
file_objecthalf of #35361Linear 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)Screenshots / Proof of Fix
Live proxies against one shared Postgres, before leg on
litellm_internal_stagingat388943ac, after leg on this PR's merge head3deadd76, same database state for both. The listing path never reaches an inference endpoint, so the upstream provider here is a stub returning a two-file OpenAI listing; no LLM call is involved in reproducing this and nothing about the fix depends on which provider serves the listSetup, shared by both legs: one owner key, one valid managed-file row, and one row whose
file_objectis missing required fields while carrying a filename, matching a partially written or schema-drifted rowBefore,
litellm_internal_stagingat388943ac: the single bad row takes the whole response down, so the caller cannot seefile-qa-valideitherAfter, merge head
3deadd76, same database state: the valid file comes back and the bad row is dropped. The returnedidis the row'sunified_file_idbecause #35362's remap landed on staging while this was open, and the two compose: bad rows are skipped, surviving rows are remappedThe skip is recorded rather than silent, naming the row and the fields that failed, and the rejected values stay out of the log
388943ac3deadd763deadd763deadd76Type
🐛 Bug Fix
✅ Test
Changes
get_user_created_file_idsvalidated every row'sfile_objectinline, guarding only againstNone. Any row that failsOpenAIFileObjectvalidation raisedValidationErrorout of the list comprehension and turned the whole listing into a 500, so one unparseable row cost the caller every file they could otherwise seeRows now go through
_parse_managed_file_object, which returnsNoneon a null or unparseable column and logs a warning, and the comprehension keeps only what parsed. This matcheslist_user_batchesin the same class, which already tolerates rows it cannot parse instead of failing the page. The null case returns early without warning, since the batch cost poller registers output and error ids with a nullfile_objectas normal operation and those rows carry no provider metadata worth showingThe warning reports
e.errors(include_input=False, include_url=False, include_context=False)rather than the stringifiedValidationError, whose message embedsinput_valuewith the rejected row's contents. Managed-file rows carry a caller-suppliedfilename, so the plain form would copy it into operational logs. Field locations, types, and messages are kept, so the diagnostics survive without the values. Non-validation failures fall back to the exception type#35362's
unified_file_idremap landed on staging while this was open and touched the same expression. The merge composes them: each row is parsed defensively, dropped if it fails, and remapped if it survivesWorth noting for anyone reading the sibling PRs on #35361: the
file_objectcolumn comes back from Prisma already decoded, which the before-leg error above shows directly (input_type=dict). The JSON-string handling proposed in #35368 is not needed on this pathFinal Attestation