Repository navigation
[BUG] LoadArtifactsTool incorrectly classifies image/svg+xml as Gemini-supported, causing 400 INVALID_ARGUMENT #5693
Description
🔴 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:
-
Install:
pip install "google-adk" "google-genai>=1.72,<2" -
Save any small SVG file as
logo.svg. -
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], )
-
Observe the 400. The same code path is exercised inside ADK whenever
LoadArtifactsToolencounters an artifact withmime_type='image/svg+xml':_is_inline_mime_type_supportedreturnsTrue,_as_safe_part_for_llmreturns 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(fd8b4929at 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-genaiclient 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:
- load_artifact for not natively supported types shouldn't explode with "Unsupported MIME Type" #4028 closed by
fdc98d5c. Same shape of bug forapplication/csv. This issue is the missed sub-case under theimage/prefix.
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 viaLoadArtifactsTooland sent to a Gemini model.
Activity
sanketpatil06 commentedon May 14, 2026
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_supportedfunction 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
1wos commentedon May 14, 2026
Thanks @sanketpatil06. Just to clarify for anyone landing here later: PR #5694 is the fix I opened (commit + tests). The
.txtworkaround you mentioned is functionally what the PR automates —image/svg+xmlfalls through to the existing text-fallback in_as_safe_part_for_llmand the model receives the SVG markup as a textPart. So users onmainwill get the same behaviour automatically once #5694 lands.fix(tools): convert image/svg+xml to text in LoadArtifactsTool
fix(tools): convert image/svg+xml to text in LoadArtifactsTool