can1357/oh-my-pi · error · ToolError
imageKind === "svg" ? "The ':img' selector only supports .sv
Error message
imageKind === "svg" ? "The ':img' selector only supports .svg and .svgz files." : `Read image file [${mimeType}] failed: unsupported image format.` What it means
After loading an image via loadImageInput or loadSvgImageInput, a falsy result means the decoder could not produce a vision-ready input: for the explicit ':img' SVG selector the file was not .svg/.svgz, and for regular images the detected format was unsupported/undecodable. The tool throws a ToolError with a selector-specific message rather than attaching garbage.
Source
Thrown at packages/coding-agent/src/tools/read.ts:864
const sizeStr = formatBytes(fileSize);
const maxStr = formatBytes(MAX_IMAGE_SIZE);
throw new ToolError(`Image file too large: ${sizeStr} exceeds ${maxStr} limit.`);
}
try {
const imageLoadOptions = {
path: readPath,
cwd: this.session.cwd,
autoResize: this.#autoResizeImages,
maxBytes: MAX_IMAGE_SIZE,
resolvedPath: absolutePath,
excludeWebP: webpExclusionForModel(this.session.getActiveModel?.()),
};
const imageInput =
imageKind === "svg"
? await loadSvgImageInput(imageLoadOptions)
: await loadImageInput({ ...imageLoadOptions, detectedMimeType: mimeType });
if (!imageInput) {
throw new ToolError(
imageKind === "svg"
? "The ':img' selector only supports .svg and .svgz files."
: `Read image file [${mimeType}] failed: unsupported image format.`,
);
}
return {
content: [
{ type: "text", text: imageInput.textNote },
{ type: "image", data: imageInput.data, mimeType: imageInput.mimeType },
],
details: {},
sourcePath: imageInput.resolvedPath,
};
} catch (error) {
// Both surface as an actionable tool error so the model can fix the input
// instead of the corrupt/oversized payload entering the transcript.
if (error instanceof ImageInputTooLargeError || error instanceof InvalidImageDataError) {
throw new ToolError(error.message);View on GitHub (pinned to 9690622007)
Solutions
- Drop the ':img' selector for non-SVG files — plain paths are auto-detected as images.
- Verify the file actually is the claimed format (file(1) / magic bytes) and re-export to PNG/JPEG if it is TIFF/BMP/HEIC.
- Re-download or re-save corrupted/truncated images.
- For SVGs, ensure the extension is .svg/.svgz and the markup is valid XML.
Example fix
// before
read('scan.tiff:img') // unsupported format
// after
$ `magick scan.tiff scan.png`
read('scan.png') Defensive patterns
Strategy: validation
Validate before calling
import { fileTypeFromBuffer } from 'file-type';
const buf = await Bun.file(p).slice(0, 4100).arrayBuffer();
const ft = await fileTypeFromBuffer(Buffer.from(buf));
const ok = (ext: string, mime?: string | null) =>
ext === 'svg' || ext === 'svgz' ? true : ['image/png','image/jpeg','image/gif','image/webp'].includes(mime ?? '');
if (!ok(p.split('.').pop() ?? '', ft?.mime)) throw new Error(`unsupported image format: ${ft?.mime ?? 'unknown'}`); Try / catch
try {
return await readTool.execute({ path: target });
} catch (e) {
if (e instanceof ToolError && /unsupported image format|only supports .svg/.test(e.message)) {
const converted = await convertToPng(target); // magick/convert
return await readTool.execute({ path: converted });
}
throw e;
} Prevention
- Don't append ':img' to non-SVG files; plain image paths are auto-detected.
- Verify actual format via magic bytes, not file extension.
- Convert TIFF/BMP/HEIC to PNG/JPEG before reading.
- Re-download truncated images; check for zero-byte files.
When it happens
Trigger: :img selector pointed at a non-SVG file (e.g. photo.png:img); a file whose detectedMimeType is not a decodable raster format (mismatched extension vs content); corrupted or zero-byte image where the loader returns null instead of throwing.
Common situations: Model/agent appending :img to a non-SVG path hoping to force image mode; files renamed to .png but actually BMP/TIFF/HEIC (unsupported formats); truncated downloads; SVG selector used on an SVG that fails rasterization so the loader returns null.
Related errors
- error.message (ImageInputTooLargeError or InvalidImageDataEr
- ${options.resolvedPath} is not a decodable ${options.image.m
- resizeImage: failed to decode image and cannot honor exclude
- invalid byte sequence: {:02x?}
- Unknown image type: ${mimeType}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/b0dfcbf38f74a0c8.
Report an issue: GitHub.