xtekky/gpt4free · error · ValueError

Unsupported media type: {media_type}

Error message

Unsupported media type: {media_type}

What it means

Thrown by copy_image() in copy_images.py when a downloaded response's content-type header is a concrete type (not application/octet-stream or binary/octet-stream, which are tolerated for magic-byte detection) and that type is absent from MEDIA_TYPE_MAP. The download is aborted rather than saved under a wrong extension.

Source

Thrown at g4f/image/copy_images.py:212

                    not os.path.exists(target_path)
                    or os.lstat(target_path).st_size <= 0
                ):
                    if not is_safe_url(image):
                        raise ValueError(f"Invalid or unsafe image url: {image}")
                    async with session.get(image, ssl=ssl) as response:
                        response.raise_for_status()
                        if target is None:
                            filename = update_filename(response, filename)
                            target_path = os.path.join(dest_dir, filename)
                        media_type = response.headers.get(
                            "content-type", "application/octet-stream"
                        )
                        if media_type not in (
                            "application/octet-stream",
                            "binary/octet-stream",
                        ):
                            if media_type not in MEDIA_TYPE_MAP:
                                raise ValueError(
                                    f"Unsupported media type: {media_type}"
                                )
                            if target is None and not media_extension:
                                media_extension = f".{MEDIA_TYPE_MAP[media_type]}"
                                target_path = f"{target_path}{media_extension}"
                        with open(target_path, "wb") as f:
                            async for chunk in response.content.iter_any():
                                f.write(chunk)

                # Auto-detect extension from file magic if still unknown
                if target is None and not media_extension:
                    with open(target_path, "rb") as f:
                        file_header = f.read(12)
                    try:
                        detected_type = is_accepted_format(file_header)
                        media_extension = f".{detected_type.split('/')[-1]}"
                        media_extension = media_extension.replace("jpeg", "jpg")
                        new_path = f"{target_path}{media_extension}"

View on GitHub (pinned to 973504e177)

Solutions

  1. Point the URL at a resource served with a supported type (png, jpeg, webp, gif, mp4, mpeg, wav, ogg, webm...).
  2. If you control the server, set Content-Type to one of the mapped values or to application/octet-stream (lets magic detection run).
  3. Register the type at startup: from g4f.image import MEDIA_TYPE_MAP; MEDIA_TYPE_MAP['image/avif'] = 'avif' (extension handling afterwards is on you).
  4. Download the bytes yourself and pass a data: URI to copy_images.

Example fix

// before
images = await copy_images(["https://cdn.example.com/photo.avif"], ...)

// after
from g4f.image import MEDIA_TYPE_MAP
MEDIA_TYPE_MAP["image/avif"] = "avif"
images = await copy_images(["https://cdn.example.com/photo.avif"], ...)
Defensive patterns

Strategy: validation

Validate before calling

from g4f.image import MEDIA_TYPE_MAP, is_safe_url
import urllib.request

def fetchable_media_type(url: str) -> bool:
    if not is_safe_url(url):
        return False
    req = urllib.request.Request(url, method="HEAD")
    with urllib.request.urlopen(req, timeout=10) as r:
        ct = r.headers.get("content-type", "application/octet-stream")
    return ct in ("application/octet-stream", "binary/octet-stream") or ct in MEDIA_TYPE_MAP

Try / catch

try:
    await copy_images([url], prompt=prompt)
except ValueError as e:
    if "Unsupported media type" in str(e):
        # fall back to manual download + data URI
        data = manual_download(url)
        return [f"data:{guess_mime(data)};base64,{b64(data)}"]
    raise

Prevention

When it happens

Trigger: A remote server answering image/webp requests with 'image/avif', 'image/heic', 'audio/aac', or 'video/x-matroska' — any type not built from EXTENSIONS_MAP. The octet-stream pair bypasses this check and falls through to file-magic extension sniffing.

Common situations: Modern image formats (avif/heif) from CDNs; unusual audio codecs from TTS providers; content negotiation returning a different type than the URL extension suggested.

Related errors


AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14). Data as JSON: /api/errors/be6a98909cb72417. Report an issue: GitHub.