{"record":{"id":"be6a98909cb72417","repo":"xtekky/gpt4free","slug":"unsupported-media-type-media-type","errorCode":null,"errorMessage":"Unsupported media type: {media_type}","messagePattern":"Unsupported media type: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"g4f/image/copy_images.py","lineNumber":212,"sourceCode":"                    not os.path.exists(target_path)\n                    or os.lstat(target_path).st_size <= 0\n                ):\n                    if not is_safe_url(image):\n                        raise ValueError(f\"Invalid or unsafe image url: {image}\")\n                    async with session.get(image, ssl=ssl) as response:\n                        response.raise_for_status()\n                        if target is None:\n                            filename = update_filename(response, filename)\n                            target_path = os.path.join(dest_dir, filename)\n                        media_type = response.headers.get(\n                            \"content-type\", \"application/octet-stream\"\n                        )\n                        if media_type not in (\n                            \"application/octet-stream\",\n                            \"binary/octet-stream\",\n                        ):\n                            if media_type not in MEDIA_TYPE_MAP:\n                                raise ValueError(\n                                    f\"Unsupported media type: {media_type}\"\n                                )\n                            if target is None and not media_extension:\n                                media_extension = f\".{MEDIA_TYPE_MAP[media_type]}\"\n                                target_path = f\"{target_path}{media_extension}\"\n                        with open(target_path, \"wb\") as f:\n                            async for chunk in response.content.iter_any():\n                                f.write(chunk)\n\n                # Auto-detect extension from file magic if still unknown\n                if target is None and not media_extension:\n                    with open(target_path, \"rb\") as f:\n                        file_header = f.read(12)\n                    try:\n                        detected_type = is_accepted_format(file_header)\n                        media_extension = f\".{detected_type.split('/')[-1]}\"\n                        media_extension = media_extension.replace(\"jpeg\", \"jpg\")\n                        new_path = f\"{target_path}{media_extension}\"","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/image/copy_images.py#L194-L230","documentation":"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.","triggerScenarios":"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.","commonSituations":"Modern image formats (avif/heif) from CDNs; unusual audio codecs from TTS providers; content negotiation returning a different type than the URL extension suggested.","solutions":["Point the URL at a resource served with a supported type (png, jpeg, webp, gif, mp4, mpeg, wav, ogg, webm...).","If you control the server, set Content-Type to one of the mapped values or to application/octet-stream (lets magic detection run).","Register the type at startup: from g4f.image import MEDIA_TYPE_MAP; MEDIA_TYPE_MAP['image/avif'] = 'avif' (extension handling afterwards is on you).","Download the bytes yourself and pass a data: URI to copy_images."],"exampleFix":"// before\nimages = await copy_images([\"https://cdn.example.com/photo.avif\"], ...)\n\n// after\nfrom g4f.image import MEDIA_TYPE_MAP\nMEDIA_TYPE_MAP[\"image/avif\"] = \"avif\"\nimages = await copy_images([\"https://cdn.example.com/photo.avif\"], ...)","handlingStrategy":"validation","validationCode":"from g4f.image import MEDIA_TYPE_MAP, is_safe_url\nimport urllib.request\n\ndef fetchable_media_type(url: str) -> bool:\n    if not is_safe_url(url):\n        return False\n    req = urllib.request.Request(url, method=\"HEAD\")\n    with urllib.request.urlopen(req, timeout=10) as r:\n        ct = r.headers.get(\"content-type\", \"application/octet-stream\")\n    return ct in (\"application/octet-stream\", \"binary/octet-stream\") or ct in MEDIA_TYPE_MAP","typeGuard":null,"tryCatchPattern":"try:\n    await copy_images([url], prompt=prompt)\nexcept ValueError as e:\n    if \"Unsupported media type\" in str(e):\n        # fall back to manual download + data URI\n        data = manual_download(url)\n        return [f\"data:{guess_mime(data)};base64,{b64(data)}\"]\n    raise","preventionTips":["Prefer URLs whose servers send standard types (png/jpeg/webp/mp4/mpeg).","HEAD-check the content-type before batch copy_images runs.","Extend MEDIA_TYPE_MAP deliberately at startup if you must support extra types."],"tags":["media","content-type","download","validation"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}