Skip to content

load_artifact for not natively supported types shouldn't explode with "Unsupported MIME Type" #4028

@Spikhalskiy

Description

@Spikhalskiy

Describe the bug

If you persist an artifact that is not an image (CSV file in this example), following an example https://github.com/google/adk-python/blob/main/contributing/samples/generate_image/agent.py, load_artafact tool call for such an artifact is followed by

2025-12-26 12:54:15,962 - INFO - _client.py:1740 - HTTP Request: POST https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent "HTTP/1.1 400 Bad Request"
2025-12-26 12:54:16,027 - ERROR - adk_web_server.py:1509 - Error in event_generator: 400 INVALID_ARGUMENT. {'error': {'code': 400, 'message': 'Unsupported MIME type: application/csv', 'status': 'INVALID_ARGUMENT'}}
Traceback (most recent call last):
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/cli/adk_web_server.py", line 1499, in event_generator
    async for event in agen:
    ...<7 lines>...
      yield f"data: {sse_event}\n\n"
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/runners.py", line 505, in run_async
    async for event in agen:
      yield event
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/runners.py", line 493, in _run_with_trace
    async for event in agen:
      yield event
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/runners.py", line 722, in _exec_with_plugin
    async for event in agen:
    ...<54 lines>...
      yield (modified_event if modified_event else event)
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/runners.py", line 482, in execute
    async for event in agen:
      yield event
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/agents/base_agent.py", line 294, in run_async
    async for event in agen:
      yield event
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/agents/llm_agent.py", line 460, in _run_async_impl
    async for event in agen:
    ...<5 lines>...
        should_pause = True
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 370, in run_async
    async for event in agen:
      last_event = event
      yield event
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 447, in _run_one_step_async
    async for llm_response in agen:
    ...<13 lines>...
          yield event
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 816, in _call_llm_async
    async for event in agen:
      yield event
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 800, in _call_llm_with_tracing
    async for llm_response in agen:
    ...<12 lines>...
      yield llm_response
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 1053, in _run_and_handle_error
    raise model_error
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 1039, in _run_and_handle_error
    async for response in agen:
      yield response
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/models/google_llm.py", line 262, in generate_content_async
    raise ce
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/adk/models/google_llm.py", line 241, in generate_content_async
    response = await self.api_client.aio.models.generate_content(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<3 lines>...
    )
    ^
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/genai/models.py", line 7006, in generate_content
    return await self._generate_content(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        model=model, contents=contents, config=parsed_config
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/genai/models.py", line 5824, in _generate_content
    response = await self._api_client.async_request(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        'post', path, request_dict, http_options
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/genai/_api_client.py", line 1434, in async_request
    result = await self._async_request(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
        http_request=http_request, http_options=http_options, stream=False
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/genai/_api_client.py", line 1367, in _async_request
    return await self._async_retry(  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        self._async_request_once, http_request, stream
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "miniforge3/envs/something/lib/python3.13/site-packages/tenacity/asyncio/__init__.py", line 111, in __call__
    do = await self.iter(retry_state=retry_state)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "miniforge3/envs/something/lib/python3.13/site-packages/tenacity/asyncio/__init__.py", line 153, in iter
    result = await action(retry_state)
             ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "miniforge3/envs/something/lib/python3.13/site-packages/tenacity/_utils.py", line 99, in inner
    return call(*args, **kwargs)
  File "miniforge3/envs/something/lib/python3.13/site-packages/tenacity/__init__.py", line 420, in exc_check
    raise retry_exc.reraise()
          ~~~~~~~~~~~~~~~~~^^
  File "miniforge3/envs/something/lib/python3.13/site-packages/tenacity/__init__.py", line 187, in reraise
    raise self.last_attempt.result()
          ~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "miniforge3/envs/something/lib/python3.13/concurrent/futures/_base.py", line 449, in result
    return self.__get_result()
           ~~~~~~~~~~~~~~~~~^^
  File "miniforge3/envs/something/lib/python3.13/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "miniforge3/envs/something/lib/python3.13/site-packages/tenacity/asyncio/__init__.py", line 114, in __call__
    result = await fn(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/genai/_api_client.py", line 1347, in _async_request_once
    await errors.APIError.raise_for_async_response(client_response)
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/genai/errors.py", line 203, in raise_for_async_response
    await cls.raise_error_async(status_code, response_json, response)
  File "miniforge3/envs/something/lib/python3.13/site-packages/google/genai/errors.py", line 225, in raise_error_async
    raise ClientError(status_code, response_json, response)
google.genai.errors.ClientError: 400 INVALID_ARGUMENT. {'error': {'code': 400, 'message': 'Unsupported MIME type: application/csv', 'status': 'INVALID_ARGUMENT'}}

It would be much more helpful if artifacts with unsupported mime types were just made downloadable as raw files in the chat window instead.

To Reproduce
Store a file into "application/csv" in the artifacts storage and make ADK WEB to load it.

Expected behavior
Files that cannot be rendered should have a download button that functions the same way it currently does on the Artifacts tab.

Metadata

Metadata

Assignees

Labels

web[Component] This issue will be transferred to adk-web

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions