{"record":{"id":"832e21bcca1a75b8","repo":"can1357/oh-my-pi","slug":"unsupported-image-type-imagepath","errorCode":null,"errorMessage":"Unsupported image type: ${imagePath}","messagePattern":"Unsupported image type: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/image-gen.ts","lineNumber":793,"sourceCode":"\t\tcase \"deepinfra\":\n\t\t\treturn findDeepInfraImageCredentials(modelRegistry, sessionId);\n\t\tcase \"gemini\":\n\t\t\treturn findGeminiImageCredentials(modelRegistry, sessionId);\n\t}\n}\n\nasync function loadImageFromPath(imagePath: string, cwd: string): Promise<InlineImageData> {\n\tconst resolved = resolveReadPath(imagePath, cwd);\n\ttry {\n\t\tconst buffer = await Bun.file(resolved).bytes();\n\t\tif (buffer.length > MAX_IMAGE_SIZE) {\n\t\t\tthrow new Error(`Image file too large: ${imagePath}`);\n\t\t}\n\n\t\tconst metadata = parseImageMetadata(buffer);\n\t\tconst mimeType = metadata?.mimeType;\n\t\tif (!mimeType) {\n\t\t\tthrow new Error(`Unsupported image type: ${imagePath}`);\n\t\t}\n\n\t\treturn { data: buffer.toBase64(), mimeType };\n\t} catch (err) {\n\t\tif (isEnoent(err)) throw new Error(`Image file not found: ${imagePath}`);\n\t\tthrow err;\n\t}\n}\n\nasync function resolveInputImage(input: ImageInput, cwd: string): Promise<InlineImageData> {\n\tif (input.path) {\n\t\treturn loadImageFromPath(input.path, cwd);\n\t}\n\n\tif (input.data) {\n\t\tconst normalized = normalizeDataUrl(input.data.trim());\n\t\tconst mimeType = normalized.mimeType ?? input.mime_type;\n\t\tif (!mimeType) {","sourceCodeStart":775,"sourceCodeEnd":811,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/image-gen.ts#L775-L811","documentation":"The tool parses magic bytes with parseImageMetadata to determine the image's mime type; if no known signature matches (PNG, JPEG, GIF, WebP, etc.), it throws this error naming the path. This catches files that are not real images — renamed text files, SVG/XML, HEIC, or truncated downloads — before they are base64'd and sent to a provider.","triggerScenarios":"loadImageFromPath reads a file whose first bytes don't match any supported image signature: an .svg (text-based), a .heic/.heif (unsupported codec), a corrupted/truncated image, or a text file with an image extension.","commonSituations":"SVG logos passed directly; iPhone HEIC photos on non-supporting setups; partially downloaded images; files renamed from .txt to .png.","solutions":["Convert the file to PNG/JPEG/WebP first (e.g. `magick logo.svg logo.png` or HEIC→JPEG)","Verify the file opens in an image viewer — corruption or truncation means re-download","Check the actual file type with `file <path>` to see what it really is","Ensure the source isn't a text/XML file with an image extension"],"exampleFix":"// before\n\"image\": \"logo.svg\"\n// after (shell)\nmagick logo.svg -resize 1024x1024 logo.png\n// tool call\n\"image\": \"logo.png\"","handlingStrategy":"validation","validationCode":"import { readFileSync } from \"node:fs\";\nconst SIGNATURES: Array<[number[], string]> = [\n\t[[0x89, 0x50, 0x4e, 0x47], \"image/png\"],\n\t[[0xff, 0xd8, 0xff], \"image/jpeg\"],\n\t[[0x47, 0x49, 0x46], \"image/gif\"],\n];\nfunction sniffImageType(path: string): string | null {\n\tconst b = readFileSync(path).subarray(0, 4);\n\tfor (const [sig, mime] of SIGNATURES) if (sig.every((v, i) => b[i] === v)) return mime;\n\treturn null;\n}","typeGuard":"function isPngOrJpeg(path: string): boolean {\n\tconst b = readFileSync(path).subarray(0, 3);\n\treturn (b[0] === 0x89 && b[1] === 0x50) || (b[0] === 0xff && b[1] === 0xd8);\n}","tryCatchPattern":"try {\n\tawait genImage({ image: path });\n} catch (err) {\n\tif (err instanceof Error && err.message.startsWith(\"Unsupported image type:\")) {\n\t\t// convert to PNG then retry, or surface to user\n\t}\n\tthrow err;\n}","preventionTips":["Run `file <path>` when unsure of the real format before invoking","Convert SVG/HEIC/AVIF inputs to PNG/JPEG first","Re-download truncated images rather than passing them as-is","Never trust file extensions — they don't determine the actual format"],"tags":["validation","magic-bytes","mime-type","image-generation"],"backgroundTag":"unsupported-image-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}