{"record":{"id":"a04dab38a5d85f98","repo":"can1357/oh-my-pi","slug":"unsupported-image-type-from-url-imageurl","errorCode":null,"errorMessage":"Unsupported image type from URL: ${imageUrl}","messagePattern":"Unsupported image type from URL: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/image-gen.ts","lineNumber":401,"sourceCode":"\tif (imageUrl.startsWith(\"data:\")) {\n\t\tconst normalized = normalizeDataUrl(imageUrl.trim());\n\t\tif (!normalized.mimeType) {\n\t\t\tthrow new Error(\"mime_type is required when providing raw base64 data.\");\n\t\t}\n\t\tif (!normalized.data) {\n\t\t\tthrow new Error(\"Image data is empty.\");\n\t\t}\n\t\treturn { data: normalized.data, mimeType: normalized.mimeType };\n\t}\n\n\tconst response = await fetchImpl(imageUrl, { signal });\n\tif (!response.ok) {\n\t\tconst rawText = await response.text();\n\t\tthrow new Error(`Image download failed (${response.status}): ${rawText}`);\n\t}\n\tconst contentType = response.headers.get(\"content-type\")?.split(\";\")[0];\n\tif (!contentType?.startsWith(\"image/\")) {\n\t\tthrow new Error(`Unsupported image type from URL: ${imageUrl}`);\n\t}\n\tconst buffer = await response.bytes();\n\treturn { data: buffer.toBase64(), mimeType: contentType };\n}\n\nfunction collectOpenRouterResponseText(message: OpenRouterMessage | undefined): string | undefined {\n\tif (!message) return undefined;\n\tif (typeof message.content === \"string\") {\n\t\tconst trimmed = message.content.trim();\n\t\treturn trimmed.length > 0 ? trimmed : undefined;\n\t}\n\tif (Array.isArray(message.content)) {\n\t\tconst texts = message.content\n\t\t\t.filter(part => part.type === \"text\")\n\t\t\t.map(part => part.text)\n\t\t\t.filter((text): text is string => Boolean(text));\n\t\tconst combined = texts.join(\"\\n\").trim();\n\t\treturn combined.length > 0 ? combined : undefined;","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/image-gen.ts#L383-L419","documentation":"After a successful download the tool checks the Content-Type header (before any ';') and requires it to start with 'image/'. If the server returns text/html (an error page), application/octet-stream, application/pdf, etc., the tool refuses to forward it as an inline image because providers accept only actual image media types.","triggerScenarios":"The fetched URL responds 200 but its content-type is not image/* — e.g. a login/interstitial HTML page, an octet-stream download endpoint, a JSON error with 200 status, or a bare IP host serving a default page.","commonSituations":"URLs that redirect to HTML viewers instead of raw bytes; object storage without a content-type set on upload; endpoints returning SVG served as text/xml; APIs that require an Accept header to serve image bytes.","solutions":["Point to the direct image URL (ends in .png/.jpg, served with image/* content-type) rather than a viewer/page URL","Set the correct Content-Type when uploading the image to object storage (e.g. image/png)","Convert the asset to a real image and pass it as a file path or data: URL instead","If serving SVG, convert to PNG — SVG is often served as text/xml and rejected"],"exampleFix":"// before\nconst url = \"https://drive.google.com/file/d/abc/view\"; // HTML page\n// after\nconst url = \"https://example.com/raw/abc.png\"; // served as image/png","handlingStrategy":"validation","validationCode":"async function isImageUrl(url: string, fetchImpl: typeof fetch): Promise<boolean> {\n\tconst res = await fetchImpl(url, { method: \"HEAD\" });\n\treturn (res.headers.get(\"content-type\") ?? \"\").startsWith(\"image/\");\n}","typeGuard":null,"tryCatchPattern":"try {\n\tawait genImage({ imageUrl });\n} catch (err) {\n\tif (err instanceof Error && err.message.startsWith(\"Unsupported image type from URL:\")) {\n\t\t// fall back: download, sniff bytes, re-serve as data: URL\n\t}\n\tthrow err;\n}","preventionTips":["Link raw asset URLs, not viewer/preview pages","Set Content-Type correctly when uploading images to object storage","HEAD-check the content-type for user-supplied URLs before invoking","Convert SVG to PNG before sharing — it's often served as text/xml"],"tags":["content-type","http","image-download","validation"],"backgroundTag":"unsupported-image-content-type","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}