GEMINI LABJP
NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaplyOMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflowsAGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactionsMEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuouslyTHROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and regionDEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaplyOMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflowsAGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactionsMEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuouslyTHROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and regionDEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20
Articles/API / SDK
API / SDK/2026-05-31Beginner

Why Gemini API Throws 'Unsupported MIME type' and How to Fix It

The 'Unsupported MIME type' error from the Gemini API has three distinct causes: a misspelled MIME string, an octet-stream upload, and a genuinely unsupported format. Here is how to tell them apart with code that actually works.

troubleshooting82error15fix10mime-typegemini-api277file-api6multimodal44

I lost half a day to a feature that sent photos taken in an iPhone app to the Gemini API for analysis. My local test images went through fine, but images coming from real devices kept getting rejected with 400 INVALID_ARGUMENT. Unsupported MIME type: image/jpg. The cause turned out to be almost embarrassingly simple: my upload code was attaching the wrong MIME type string.

As an indie developer who has run an app business since 2014, I have been handing images and audio to multimodal APIs far more often over the past year or two. Unsupported MIME type is one of those errors where the message looks like one thing but the root cause splits into three. Without knowing how to isolate them, it is easy to burn time. Let me work through them in order.

Start with the spelling — image/jpg does not exist

The most common cause is a misspelled MIME type. image/jpg is especially tempting because the file extension is .jpg, but it is not a real MIME type. The correct MIME type for JPEG is image/jpeg.

from google import genai
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
with open("photo.jpg", "rb") as f:
    image_bytes = f.read()
 
# ❌ Rejected: Unsupported MIME type: image/jpg
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=[
        {"inline_data": {"mime_type": "image/jpg", "data": image_bytes}},
        "Describe what is in this image",
    ],
)

Changing image/jpg to image/jpeg is enough to make it pass.

# ✅ Correct spelling
{"inline_data": {"mime_type": "image/jpeg", "data": image_bytes}}

Gemini accepts five image MIME types: image/png, image/jpeg, image/webp, image/heic, and image/heif. HEIC (image/heic), the default format on the iPhone, can be passed as-is, so there is no need to convert it to JPEG first. This is a point I find is not widely known.

If you map extensions to MIME types yourself, let Python's standard library do it to avoid typos.

import mimetypes
 
mime_type, _ = mimetypes.guess_type("photo.jpg")
print(mime_type)  # image/jpeg (the correct spelling)

Check whether the File API stored it as octet-stream

The second trap is when a file uploaded through the File API ends up with a MIME type of application/octet-stream. This happens when you upload files larger than 20MB, or files you reuse across requests, to the File API.

client.files.upload() infers the MIME type from the extension and contents, but when inference fails it registers the file as application/octet-stream (generic binary). Passing that straight into generate_content gets rejected, because octet-stream is not a supported input type.

Print the MIME type right after uploading to see whether inference missed.

uploaded = client.files.upload(file="recording.m4a")
print(uploaded.mime_type)  # application/octet-stream is a red flag

The fix is to specify the MIME type explicitly at upload time. The newer google-genai SDK accepts it via config.

from google.genai import types
 
uploaded = client.files.upload(
    file="recording.m4a",
    config=types.UploadFileConfig(mime_type="audio/mp4"),
)
print(uploaded.mime_type)  # audio/mp4
 
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=[uploaded, "Transcribe this audio"],
)

Stop relying on the extension and state what you are sending every time. That alone clears up nearly all octet-stream errors.

If it is still rejected, the format itself is unsupported

If the spelling is right and you specified the MIME type but still see Unsupported MIME type, there is a good chance Gemini genuinely does not support that format.

Audio and video in particular vary by model and endpoint. A frequent offender is the .m4a that the iPhone Voice Memos app produces. As a container it is accepted as audio/mp4, but sending it with the non-standard audio/m4a or audio/x-m4a gets it rejected. When you just need it to work, the fastest path is to convert it to a format with stable support.

# Convert m4a to mp3 with ffmpeg before passing it in
import subprocess
 
subprocess.run([
    "ffmpeg", "-i", "voice.m4a", "-acodec", "libmp3lame", "voice.mp3"
], check=True)
 
uploaded = client.files.upload(
    file="voice.mp3",
    config=types.UploadFileConfig(mime_type="audio/mp3"),
)

As of now, the main MIME types Gemini accepts are images (image/png, image/jpeg, image/webp, image/heic, image/heif), audio (audio/wav, audio/mp3, audio/aiff, audio/aac, audio/ogg, audio/flac), and documents (application/pdf and plain-text formats). Checking once, before you build, whether the file types you handle are on this list saves a scramble later. Because the spec changes from time to time, it is worth getting into the habit of confirming the current table in the official file prompting documentation.

A small habit to keep it from recurring

This error shows up precisely in production, where you cannot predict what files users will send. In my case, once I started rejecting disallowed MIME types with a whitelist at the point the app accepts an upload, I could stop problematic files before they ever reached the API.

SUPPORTED_IMAGE = {"image/png", "image/jpeg", "image/webp", "image/heic", "image/heif"}
 
def validate_image(mime_type: str) -> None:
    if mime_type not in SUPPORTED_IMAGE:
        raise ValueError(
            f"Unsupported image format: {mime_type}. "
            f"Supported: {', '.join(sorted(SUPPORTED_IMAGE))}"
        )

Translating the error from "the Gemini API refused this" into "this format is not supported" in the user's own words also makes support conversations much easier.

If you want a first step, print the MIME type string in the code that is currently throwing Unsupported MIME type. If you see image/jpg or application/octet-stream, your cause is one of the ones above.

Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

API / SDK2026-05-30
Why Gemini 2.5 Pro Rejects thinkingBudget: 0 (and How to Fix It)
Setting thinkingBudget to 0 on Gemini 2.5 Pro returns a 400 INVALID_ARGUMENT error. Here is why the per-model thinking budget ranges differ, how to minimize thinking on Pro the right way, and when to switch to Flash, with Python and JavaScript examples.
API / SDK2026-04-14
Veo API Not Working? Common Errors and How to Fix Them
Troubleshoot common Veo API errors including polling implementation mistakes, safety filter rejections, quota exceeded, and video file download failures. With working Python code examples.
API / SDK2026-04-10
How to Fix Gemini API JSON and Structured Output Errors
Troubleshoot Gemini API JSON Mode and Structured Output errors including malformed JSON, schema violations, and truncated responses with step-by-step solutions and code examples.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →