Repository navigation
fix(azure): strip litellm format field from file and image content parts - #41275
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
|
Greptile SummaryThis PR removes LiteLLM-only
Confidence Score: 5/5The PR appears safe to merge, with the previous test rebinding issue fixed and no new actionable failures introduced The latest change binds transformed messages to
|
| Filename | Overview |
|---|---|
| litellm/litellm_core_utils/prompt_templates/factory.py | Filters format from Azure-bound file and image payloads while preserving the remaining fields |
| tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py | Verifies direct Azure conversion strips format from both supported content shapes |
| tests/test_litellm/llms/azure/chat/test_azure_chat_gpt_transformation.py | Covers the managed-file request path and now keeps original and transformed messages in separate variables |
Reviews (3): Last reviewed commit: "test(azure): avoid rebinding messages in..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…trings Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
| "content": [ | ||
| {"type": "text", "text": "Summarize this file"}, | ||
| {"type": "file", "file": {"file_id": managed_file_id}}, | ||
| ], |
There was a problem hiding this comment.
Reassigning messages violates the repository's no-rebinding directive. Bind the transformed result to a new Final variable before merging
Context Used: CLAUDE.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f219535. Configure here.
TLDR
Problem this solves:
chat/completionsagainst Azure fail withUnknown parameter: 'messages[0].content[1].file.format'formatkey that OpenAI strips but Azure did notHow it solves it:
convert_to_azure_openai_messagesnow dropsformatfromfileand dict-shapedimage_urlpartsUser Flow
Before: a developer attaching an uploaded file to an Azure chat request gets a 400 from Azure
target_model_names: "azure-gpt-5.4"and get back a managed file idazure-gpt-5.4with content[{"type": "text", ...}, {"type": "file", "file": {"file_id": "<managed-file-id>"}}]400 AzureException BadRequestError - Unknown parameter: 'messages[0].content[1].file.format'After: the same request succeeds
target_model_names: "azure-gpt-5.4"and get back a managed file idRelevant issues
Customer report via Pylon #8654
Affected release
Linear ticket
Resolves LIT-7809
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@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
Shared setup: two proxies against the real Azure OpenAI deployment, one at the merge base and one at this PR's tip, each in its own worktree with its own venv, a fresh Postgres database, a random port, and
--num_workers 2.lit7809_sample.pdf(630 bytes) andlit7809_sample.txt(56 bytes) both contain the sentence "The secret word is pineapple."$B64is the base64 of a 1x1 red PNG. The upload usespurpose=assistantsbecause Azure OpenAI rejectspurpose=user_dataon the dated api-versions ("Invalid value for purpose.")Before (2e06d19)
Case 1: PDF managed file
Case 2: text managed file
Case 3: image_url with format
$B64is the base64 of a 1x1 red PNGAfter (f219535)
Case 1: PDF managed file
Case 2: text managed file
Case 3: image_url with format
$B64is the base64 of a 1x1 red PNGObservations
image_url.formatreturned 200 on both sidesRegression sweep (/live-pr-risk)
Same config, two proxies booted with
--num_workers 2on a fresh Postgres each, one at the merge base and one at the tip, then the tip with currentmainmerged in (130f2e789b). Only the two managed-file cases change; everything around them is identical on all threeThe 500 on the file part without a
fileobject comes from the managed-files hook (get_file_ids_from_messages) before any transform runs, so it is the same on both sides and outside this PR. Spend logs on both sides carry the same rows apart from the two calls that went from failure to successType
🐛 Bug Fix
Caveats (if any)
Low
image_url.formatis also dropped for Azure to match the OpenAI path; the live run shows Azure already returned 200 with it present at the merge base (Case 3), so that part is parity rather than a fix_azure_file_helperwritesfile: {}when a file part has nofileobject where the OpenAI path raises BadRequestError; through the proxy that shape never reaches either, the managed-files hook 500s on it first (sweep above), so the two paths only differ on direct SDK usemainafter the merge base (2026-09-15 11:38 -0700) and none touching this PR's files, so the branch is not rebased: 22 Together AI tests across local_testing_part1, local_testing_part2, and llm_translation_testing fail with "Unable to access non-serverless model openai/gpt-oss-20b" (fixed by test(together_ai): move request-shape checks to the mapped file, drop the live ones #41360); litellm_router_testingtest_async_fallbacksasserts on a deployment-selection log line (fixed by test(router): ignore deployment-selection logs in the fallback log assertion #41358); logging_testingtest_generic_api_callback_sumologic_uses_ndjson(fixed by test(logging): pick this test's own records out of the shared log batch #41487). The newestmainpipeline (89785) is green on all fiveFinal Attestation
Link to Devin session: https://app.devin.ai/sessions/378f7876fa414215b1c0d43663ca494c
Open in Devin Desktop: https://app.devin.ai/desktop/session/378f7876fa414215b1c0d43663ca494c?variant=devin