Skip to content

[BUG] LoadArtifactsTool incorrectly classifies image/svg+xml as Gemini-supported, causing 400 INVALID_ARGUMENT #5693

Closed

Description

@1wos

🔴 Required Information

Describe the Bug:

_is_inline_mime_type_supported in LoadArtifactsTool returns True for image/svg+xml via the image/ prefix match at src/google/adk/tools/load_artifacts_tool.py:32-36, so SVG artifacts get forwarded to Gemini as inline image data. Gemini rejects every SVG MIME variant with 400 INVALID_ARGUMENT - Unsupported MIME type: image/svg+xml, instead of being text-converted like CSV / JSON / XML are since #4028.

Steps to Reproduce:

  1. Install: pip install "google-adk" "google-genai>=1.72,<2"

  2. Save any small SVG file as logo.svg.

  3. Run this script:

    from google import genai
    from google.genai import types
    
    client = genai.Client(api_key="<YOUR_KEY>")
    with open("logo.svg", "rb") as f:
        part = types.Part.from_bytes(data=f.read(), mime_type="image/svg+xml")
    
    client.models.generate_content(
        model="gemini-2.5-flash",
        contents=["Describe this.", part],
    )
  4. Observe the 400. The same code path is exercised inside ADK whenever LoadArtifactsTool encounters an artifact with mime_type='image/svg+xml': _is_inline_mime_type_supported returns True, _as_safe_part_for_llm returns the raw artifact, and the request reaches Gemini as inline image data.

Expected Behavior:

LoadArtifactsTool should recognise that image/svg+xml is not actually accepted by Gemini as inline image data, and route the artifact through the existing text-fallback path (the same one used for application/csv / application/json / application/xml since #4028). The SVG markup would then be delivered to the model as a text Part.

Observed Behavior:

The artifact is forwarded as inline image data and the Gemini API returns:

google.genai.errors.ClientError: 400 INVALID_ARGUMENT.
{'error': {'code': 400, 'message': 'Unsupported MIME type: image/svg+xml', 'status': 'INVALID_ARGUMENT'}}

The agent run aborts with this error instead of degrading gracefully.

Environment Details:

  • ADK Library Version (pip show google-adk): main (fd8b4929 at time of testing)
  • Desktop OS: macOS (Darwin 25.4.0)
  • Python Version: 3.13 (also reproduces on 3.11)

Model Information:

  • Are you using LiteLLM: No (reproduced against the native Gemini path; the SDK that fails is the google-genai client used by ADK)
  • Which model is being used: gemini-2.5-flash

🟡 Optional Information

Regression:

Not a regression. The MIME validation in load_artifacts_tool.py was added in fdc98d5c (close #4028, 2026-01-15) to convert unsupported artifacts to text rather than crashing on them. SVG slipped through the image/ prefix check at that time and was never explicitly handled.

Additional Context:

Tested matrix against gemini-2.5-flash via google-genai==1.75.0 to confirm image/svg+xml is the only sub-case that needs special handling today:

MIME Result
image/png, image/jpeg, image/webp accepted
image/avif, image/gif accepted (not in Google docs but works)
audio/mpeg, audio/mp3, video/mp4, video/webm accepted
application/pdf accepted
image/svg+xml 400 INVALID_ARGUMENT
image/svg, application/svg+xml, image/xml 400 (non-standard, included for completeness)
text/xml (workaround) accepted but Gemini reads the bytes as plain XML text, not as a rendered image. Visual content gets hallucinated.

So audio/* and video/* don't have the same gap; only the image/ prefix has the SVG sub-case.

Proposed fix:

Add an explicit denylist for subtypes that match a supported prefix but that Gemini still rejects, and route SVG through the existing text-fallback path. Same shape as the #4028 fix:

_GEMINI_UNSUPPORTED_INLINE_SUBTYPES = frozenset({'image/svg+xml'})

_TEXT_LIKE_MIME_TYPES = frozenset({
    'application/csv',
    'application/json',
    'application/xml',
    'image/svg+xml',  # XML-based; falls through here after the denylist above
})

def _is_inline_mime_type_supported(mime_type):
    normalized = _normalize_mime_type(mime_type)
    if not normalized:
        return False
    if normalized in _GEMINI_UNSUPPORTED_INLINE_SUBTYPES:
        return False
    return normalized.startswith(_GEMINI_SUPPORTED_INLINE_MIME_PREFIXES) or (
        normalized in _GEMINI_SUPPORTED_INLINE_MIME_TYPES
    )

PR with this fix plus a test_load_artifacts_converts_svg_to_text mirroring the existing CSV test: #5694.

Related:

Minimal Reproduction Code:

from google import genai
from google.genai import types

client = genai.Client(api_key="...")
with open("any.svg", "rb") as f:
    part = types.Part.from_bytes(data=f.read(), mime_type="image/svg+xml")

client.models.generate_content(
    model="gemini-2.5-flash",
    contents=["Describe this.", part],
)
# google.genai.errors.ClientError: 400 INVALID_ARGUMENT.
# 'Unsupported MIME type: image/svg+xml'

How often has this issue occurred?:

  • Always (100%) when an artifact with mime_type='image/svg+xml' is loaded via LoadArtifactsTool and sent to a Gemini model.

Activity

  1. sanketpatil06 commented on May 14, 2026

    @sanketpatil06

    Hi @1wos , Thanks for reporting this and providing details.
    We've looked into this, and it seems the current logic for MIME type handling in the LoadArtifactsTool might be broader than intended, which could explain the behavior you're observing with image/svg+xml files. Our initial analysis suggests that the _is_inline_mime_type_supported function may be the key area to focus on for a resolution.

    Thanks for raising PR(#5694). It is currently under review and it will get merged once it is approved and everything looks good.

    Workaround: In the meantime, you can work around this issue by manually converting your SVG files into a supported format before loading them as artifacts. For example, you can either:

    • Convert the SVG to a PNG file if you need the image representation.

    • Extract the XML content into a plain .txt file if you need the model to analyze the code.

    Thanks again for your contribution

  2. 1wos commented on May 14, 2026

    @1wos
    ContributorAuthor

    Thanks @sanketpatil06. Just to clarify for anyone landing here later: PR #5694 is the fix I opened (commit + tests). The .txt workaround you mentioned is functionally what the PR automates — image/svg+xml falls through to the existing text-fallback in _as_safe_part_for_llm and the model receives the SVG markup as a text Part. So users on main will get the same behaviour automatically once #5694 lands.

  3. added a commit that references this issue on Jun 16, 2026
    f9be94c
  4. added a commit that references this issue on Aug 11, 2026
    a02461e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

tools[Component] This issue is related to tools

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions