Merge pull request #36021 from BerriAI/claude/open-source-pr-merge-ven7h6
Some checks failed
CI Coverage / assert-ci-coverage (push) Waiting to run
CodSpeed Benchmarks / benchmarks (push) Waiting to run
UI Unit Tests / ui-unit-tests (push) Waiting to run
Unit Tests: Core Utilities / core-utils (push) Waiting to run
Unit Tests: Documentation Validation / documentation (push) Waiting to run
Unit Tests: Enterprise, Google GenAI & Routing / enterprise-routing (push) Waiting to run
Unit Tests: Integrations (Callbacks & Logging) / integrations (push) Waiting to run
Unit Tests: LLM Provider Transformations / Vertex AI (push) Waiting to run
Unit Tests: LLM Provider Transformations / All Other Providers (push) Waiting to run
Unit Tests: MCP, Secrets, Containers & Misc / misc (push) Waiting to run
Unit Tests: Proxy Auth & Key Management / proxy-auth (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run
Publish basedpyright base counts / publish (push) Waiting to run
Code Quality Checks / code-quality (push) Waiting to run
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Waiting to run
Unit Tests: Proxy DB Operations / auth-checks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / budgets (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / custom-logging (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / db-and-spend (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / key-generation (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / logging-misc (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-runtime (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-server-core (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-utils (push) Blocked by required conditions
Unit Tests: Proxy API Endpoints / proxy-endpoints (push) Waiting to run
Unit Tests: Proxy API Endpoints / proxy-server (push) Waiting to run
Unit Tests: Proxy Infrastructure / proxy-infra (push) Waiting to run
Unit Tests: Proxy Legacy Tests / auth-and-jwt (push) Waiting to run
Unit Tests: Proxy Legacy Tests / key-generation (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-config (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-response-and-misc (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-server (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-server-extras (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-token-counter (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-user-auth-and-spend (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-utils (push) Waiting to run
Unit Tests: Responses, Caching & Types / responses-caching-types (push) Waiting to run
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled

fix(managed_files): skip unparseable rows when listing managed files
This commit is contained in:
Mateo Wang 2026-08-06 18:55:03 -07:00 committed by GitHub
commit 795fa439b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 70 additions and 4 deletions

View file

@ -8,6 +8,7 @@ from typing import TYPE_CHECKING, Any, Dict, Final, List, Literal, Optional, Uni
from uuid import NAMESPACE_URL, uuid5
from fastapi import HTTPException
from pydantic import ValidationError
import litellm
from litellm import Router, verbose_logger
@ -74,6 +75,26 @@ else:
PrismaClient = Any
def _parse_managed_file_object(
raw_file_object: object, unified_file_id: str
) -> Optional[OpenAIFileObject]:
if raw_file_object is None:
return None
try:
return OpenAIFileObject.model_validate(raw_file_object)
except ValidationError as e:
verbose_logger.warning(
f"Failed to parse managed file object {unified_file_id}: "
f"{e.errors(include_input=False, include_url=False, include_context=False)}"
)
return None
except Exception as e:
verbose_logger.warning(
f"Failed to parse managed file object {unified_file_id}: {type(e).__name__}"
)
return None
class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints):
# Class variables or attributes
def __init__(
@ -384,11 +405,14 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints):
}
)
return [
OpenAIFileObject.model_validate(row.file_object).model_copy(
update={"id": row.unified_file_id}
)
parsed_file_object.model_copy(update={"id": row.unified_file_id})
for row in file_ids
if row.file_object is not None
if (
parsed_file_object := _parse_managed_file_object(
row.file_object, row.unified_file_id
)
)
is not None
]
async def check_managed_file_id_access(

View file

@ -8,6 +8,7 @@ async_post_call_success_hook when processing completed batch responses.
import asyncio
import base64
import json
import logging
import pytest
from typing import Optional
@ -189,6 +190,47 @@ async def test_get_user_created_file_ids_remaps_stored_raw_provider_id_to_unifie
assert files[0].purpose == raw_provider_object.purpose
@pytest.mark.asyncio
async def test_parse_managed_file_object_warning_omits_rejected_values(caplog):
from litellm_enterprise.proxy.hooks.managed_files import (
_parse_managed_file_object,
)
with caplog.at_level(logging.WARNING):
parsed = _parse_managed_file_object(
{"id": "file-corrupt", "object": "file", "filename": "confidential.jsonl"},
"unified-corrupt",
)
assert parsed is None
assert "unified-corrupt" in caplog.text
assert "bytes" in caplog.text
assert "confidential.jsonl" not in caplog.text
@pytest.mark.asyncio
async def test_get_user_created_file_ids_skips_unparseable_rows():
managed_files = _make_managed_files_instance()
managed_files.prisma_client.db.litellm_managedfiletable.find_many = AsyncMock(
return_value=[
MagicMock(
file_object={"id": "file-corrupt", "object": "file"},
unified_file_id="unified-corrupt",
),
MagicMock(
file_object=_make_file_object().model_dump(),
unified_file_id="unified-valid",
),
]
)
files = await managed_files.get_user_created_file_ids(
_make_user_api_key_dict(), ["file-output-abc"]
)
assert [file.id for file in files] == ["unified-valid"]
@pytest.mark.asyncio
async def test_should_fallback_when_no_router():
"""