Skip to content

LiteLLM: file_uri with unknown or generic MIME type causes cryptic downstream ValueError #5022

Closed

Description

@kronos3610

Summary

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

from google.genai import types

part = 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.

Activity

  1. added
    models[Component] This issue is related to model support
    on Mar 27, 2026
  2. added theissue type on Mar 27, 2026
  3. surajksharma07 commented on Apr 23, 2026

    @surajksharma07
    Collaborator

    @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!

  4. kronos3610 commented on Apr 23, 2026

    @kronos3610
    ContributorAuthor

    @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.

  5. surajksharma07 commented on Apr 24, 2026

    @surajksharma07
    Collaborator

    @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.

  6. kronos3610 commented on Apr 25, 2026

    @kronos3610
    ContributorAuthor

    @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:

    if not mime_type or mime_type == "application/octet-stream":
        type_label = mime_type or "(unknown)"
        raise ValueError(
            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.

  7. surajksharma07 commented on Apr 25, 2026

    @surajksharma07
    Collaborator

    @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.

  8. kronos3610 commented on Apr 26, 2026

    @kronos3610
    ContributorAuthor

    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.

  9. surajksharma07 commented on Apr 28, 2026

    @surajksharma07
    Collaborator

    @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!

  10. surajksharma07 commented on Apr 28, 2026

    @surajksharma07
    Collaborator

    @GWeale Please have a look into it once.

  11. removed
    request clarification[Status] The maintainer need clarification or more information from the author
    on Apr 28, 2026
  12. kronos3610 commented on May 10, 2026

    @kronos3610
    ContributorAuthor

    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!

  13. surajksharma07 commented on May 18, 2026

    @surajksharma07
    Collaborator

    @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!

  14. added a commit that references this issue on Jun 26, 2026
    42eceb3
  15. added a commit that references this issue on Aug 11, 2026
    ec4b351
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

models[Component] This issue is related to model supportneeds review[Status] The PR/issue is awaiting review from the maintainer

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions