You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
LiteLLM: file_uri with unknown or generic MIME type causes cryptic downstream ValueError #5022
When a Part with file_data.file_uri has no determinable MIME type (no extension, no display_name, no explicit mime_type field), the library falls back to application/octet-stream. This produces a cryptic ValueError deep inside LiteLLM rather than a clear error at the ADK layer.
The same problem occurs when the caller explicitly sets mime_type to application/octet-stream. Both paths reach the same failure point in LiteLLM with no useful message.
Root Cause
The constant _DEFAULT_MIME_TYPE = "application/octet-stream" was added to satisfy LiteLLM's Vertex AI backend requirement for a non-empty format field in file objects. However application/octet-stream is not in _SUPPORTED_FILE_CONTENT_MIME_TYPES and is not a type any backend can meaningfully process.
This creates an inconsistency between the two content paths:
The inline_data path raises ValueError immediately for unsupported MIME types (fail-fast behavior).
The file_data path silently falls back to application/octet-stream and fails later with a cryptic error.
GcsArtifactService generates URIs like gs://bucket/artifact/0 with no extension and no MIME type set, making ADK's own artifact system the primary trigger for this fallback. The library raises an error caused by a value it generated itself.
Steps to Reproduce
fromgoogle.genaiimporttypespart=types.Part(
file_data=types.FileData(
file_uri="gs://bucket/artifact/0"
)
)
# Passing this part to a LiteLlm model call results in a cryptic# ValueError from LiteLLM internals with no guidance on how to fix it.
Expected Behavior
A clear ValueError at the ADK layer with an actionable message telling the user to set file_data.mime_type explicitly on the Part.
Actual Behavior
A cryptic ValueError originating from inside LiteLLM with no reference to mime_type or how to resolve it.
Additional Context
The same failure occurs when mime_type is explicitly set to application/octet-stream by the caller. The type is semantically equivalent to an unknown type and no backend in this pipeline can use it. For OpenRouter specifically, LiteLLM strips the format field entirely before the request goes out so the value never reaches the provider regardless.
The fix aligns the file_data path with the existing fail-fast behavior of the inline_data path.
@surajksharma07 The workaround assumes the caller always knows the MIME type, but in my pipeline the type comes from an external API that occasionally sends application/octet-stream incorrectly, which is a very common scenario. The fix isn't about inference it's about surfacing a clear error at the right layer so retry logic can kick in, rather than silently propagating a bad value downstream.
@Raman369AI when application/octet-stream is supplied explicitly by an upstream API, it's truthy and bypasses the if not mime_type guard in PR #5023 entirely, so your exact scenario would still flow through to LiteLLM and fail cryptically even after that fix lands.
The design intent is correct and consistent with how the inline_data path already handles unsupported types at ADK's boundary.
Could you extend #5023 with a second guard immediately after MIME resolution:
if mime_type == "application/octet-stream":
raise ValueError(
f"'application/octet-stream' cannot be processed by any LiteLLM backend; "
f"set file_data.mime_type to a specific supported type for file_uri '{part.file_data.file_uri}'."
)
That way retry logic gets a consistent, catchable signal from ADK regardless of whether the bad type came from the inference fallback or an upstream API.
@surajksharma07 Thanks for the close look! I think this case is already covered - the guard at lite_llm.py line 1129 is a combined check, not just if not mime_type:
ifnotmime_typeormime_type=="application/octet-stream":
type_label=mime_typeor"(unknown)"raiseValueError(
f"Cannot process file_uri {part.file_data.file_uri!r}: MIME type"f" {type_label!r} is not supported. Please set a specific MIME"" type on `file_data.mime_type`."
)
So an explicit application/octet-stream from an upstream API hits the same raise as the inference-fallback case — retry logic gets the consistent signal you described.
On positioning: the guard is intentionally placed after _requires_file_uri_fallback. Providers like anthropic and non-Gemini Vertex AI take the text-fallback branch and continue before reaching this point - they don't require a MIME type at all, so raising earlier (immediately after MIME resolution) would regress those paths. The comment block just above the guard documents this.
Happy to split it into two separate checks if that reads more clearly at review time - let me know what you prefer.
Traced the mainline source end-to-end now: MIME resolution at lines 1107–1121, the text-fallback branch via _requires_file_uri_fallback at 1134–1148 (where Anthropic and non-Gemini Vertex already continue without needing a MIME type), and file_object["format"] = mime_type at 1153 which is the only assignment that actually reaches LiteLLM.
The combined not mime_type or mime_type == "application/octet-stream" guard belongs exactly in that window — placing it earlier would incorrectly intercept providers that have already exited via the text-fallback path, regressing valid calls to Anthropic and non-Gemini Vertex.
The positioning is correct.
On the split-vs-combined question: keep the single combined guard.
Two separate if blocks with identical error paths and no distinct behaviour add lines without adding clarity, and the type_label = mime_type or "(unknown)" pattern already disambiguates the two trigger conditions in the error message itself — callers can see whether the issue was a missing MIME type or an unsupported one.
One thing to confirm before this is merge-ready: do the unit tests exercise both branches —
(1) a file_uri with no inferrable MIME type where resolution falls through to None, and
(2) an explicit mime_type="application/octet-stream" passed in by an upstream caller?
Hi @surajksharma07 - just to close the loop on your question about test coverage.
Both branches are now covered in commit 6a7b6a37 on PR #5023:
Branch (1) - MIME resolves to None: test_content_to_message_param_user_message_file_uri_without_mime_type and test_get_content_file_uri_default_mime_type
Branch (2) - explicit mime_type="application/octet-stream" from an upstream caller: test_content_to_message_param_user_message_file_uri_explicit_octet_stream(new) and test_get_content_file_uri_explicit_octet_stream_raises
All four pass cleanly. Let me know if anything else is needed from our side.
@Raman369AI The four tests cover exactly what's needed — a parameter-path test and an explicit raise test for each branch, with test_get_content_file_uri_explicit_octet_stream_raises specifically closing the upstream-API case that started this thread.
Guard positioning, combined check, error messages, and test coverage are all confirmed correct — nothing outstanding from our side.
Tagging @GWeale for the final merge review!
Hi @GWeale - just a gentle ping. @surajksharma07 confirmed guard positioning, test coverage, and error messages are all correct on PR #5023 and tagged you for the final merge review on April 28. No rush at all, just wanted to make sure it didn't slip through. Happy to adjust anything if needed!
@Raman369AI the new commit c7eb917 is consistent with what was confirmed before — same test structure, both ValueError branches (null MIME resolution and explicit application/octet-stream) still covered.
Verified that mainline _get_content at lines 1113–1120 is still falling through to _DEFAULT_MIME_TYPE with no guard, so this fix is still needed and the PR design remains correct: the combined check belongs in the window after _requires_file_uri_fallback exits (line 1148) and before file_object["format"] = mime_type (line 1153) — which is exactly where it is.
@GWeale guard positioning, combined not mime_type or mime_type == "application/octet-stream" check, error messages, and the four-test suite are all confirmed good.
Would appreciate your review on PR #5023 when you get a chance!
Activity
surajksharma07 commentedon Apr 23, 2026
@Raman369AI Thanks for the detailed writeup.
As an immediate workaround, explicitly setting file_data.mime_type on the Part avoids the silent fallback entirely and should unblock you for now.
Could you try the fix from PR #5023 on your end and verify it covers both the no-MIME-type case and the explicit application/octet-stream case?
That'll help speed up the merge once confirmed!
kronos3610 commentedon Apr 23, 2026
@surajksharma07 The workaround assumes the caller always knows the MIME type, but in my pipeline the type comes from an external API that occasionally sends application/octet-stream incorrectly, which is a very common scenario. The fix isn't about inference it's about surfacing a clear error at the right layer so retry logic can kick in, rather than silently propagating a bad value downstream.
surajksharma07 commentedon Apr 24, 2026
@Raman369AI when application/octet-stream is supplied explicitly by an upstream API, it's truthy and bypasses the if not mime_type guard in PR #5023 entirely, so your exact scenario would still flow through to LiteLLM and fail cryptically even after that fix lands.
The design intent is correct and consistent with how the inline_data path already handles unsupported types at ADK's boundary.
Could you extend #5023 with a second guard immediately after MIME resolution:
That way retry logic gets a consistent, catchable signal from ADK regardless of whether the bad type came from the inference fallback or an upstream API.
kronos3610 commentedon Apr 25, 2026
@surajksharma07 Thanks for the close look! I think this case is already covered - the guard at
lite_llm.pyline 1129 is a combined check, not justif not mime_type:So an explicit
application/octet-streamfrom an upstream API hits the same raise as the inference-fallback case — retry logic gets the consistent signal you described.On positioning: the guard is intentionally placed after
_requires_file_uri_fallback. Providers like anthropic and non-Gemini Vertex AI take the text-fallback branch andcontinuebefore reaching this point - they don't require a MIME type at all, so raising earlier (immediately after MIME resolution) would regress those paths. The comment block just above the guard documents this.Happy to split it into two separate checks if that reads more clearly at review time - let me know what you prefer.
surajksharma07 commentedon Apr 25, 2026
@Raman369AI
Traced the mainline source end-to-end now: MIME resolution at lines 1107–1121, the text-fallback branch via _requires_file_uri_fallback at 1134–1148 (where Anthropic and non-Gemini Vertex already continue without needing a MIME type), and file_object["format"] = mime_type at 1153 which is the only assignment that actually reaches LiteLLM.
The combined not mime_type or mime_type == "application/octet-stream" guard belongs exactly in that window — placing it earlier would incorrectly intercept providers that have already exited via the text-fallback path, regressing valid calls to Anthropic and non-Gemini Vertex.
The positioning is correct.
On the split-vs-combined question: keep the single combined guard.
Two separate if blocks with identical error paths and no distinct behaviour add lines without adding clarity, and the type_label = mime_type or "(unknown)" pattern already disambiguates the two trigger conditions in the error message itself — callers can see whether the issue was a missing MIME type or an unsupported one.
One thing to confirm before this is merge-ready: do the unit tests exercise both branches —
(1) a file_uri with no inferrable MIME type where resolution falls through to None, and
(2) an explicit mime_type="application/octet-stream" passed in by an upstream caller?
Team is looking more into it.
kronos3610 commentedon Apr 26, 2026
Hi @surajksharma07 - just to close the loop on your question about test coverage.
Both branches are now covered in commit
6a7b6a37on PR #5023:None:test_content_to_message_param_user_message_file_uri_without_mime_typeandtest_get_content_file_uri_default_mime_typemime_type="application/octet-stream"from an upstream caller:test_content_to_message_param_user_message_file_uri_explicit_octet_stream(new) andtest_get_content_file_uri_explicit_octet_stream_raisesAll four pass cleanly. Let me know if anything else is needed from our side.
surajksharma07 commentedon Apr 28, 2026
@Raman369AI The four tests cover exactly what's needed — a parameter-path test and an explicit raise test for each branch, with test_get_content_file_uri_explicit_octet_stream_raises specifically closing the upstream-API case that started this thread.
Guard positioning, combined check, error messages, and test coverage are all confirmed correct — nothing outstanding from our side.
Tagging @GWeale for the final merge review!
surajksharma07 commentedon Apr 28, 2026
@GWeale Please have a look into it once.
kronos3610 commentedon May 10, 2026
Hi @GWeale - just a gentle ping. @surajksharma07 confirmed guard positioning, test coverage, and error messages are all correct on PR #5023 and tagged you for the final merge review on April 28. No rush at all, just wanted to make sure it didn't slip through. Happy to adjust anything if needed!
surajksharma07 commentedon May 18, 2026
@Raman369AI the new commit c7eb917 is consistent with what was confirmed before — same test structure, both ValueError branches (null MIME resolution and explicit application/octet-stream) still covered.
Verified that mainline _get_content at lines 1113–1120 is still falling through to _DEFAULT_MIME_TYPE with no guard, so this fix is still needed and the PR design remains correct: the combined check belongs in the window after _requires_file_uri_fallback exits (line 1148) and before file_object["format"] = mime_type (line 1153) — which is exactly where it is.
@GWeale guard positioning, combined not mime_type or mime_type == "application/octet-stream" check, error messages, and the four-test suite are all confirmed good.
Would appreciate your review on PR #5023 when you get a chance!
fix: raise ValueError for unsupported MIME types in file_data URI path
fix: raise ValueError for unsupported MIME types in file_data URI path