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

  1. Drop the ':img' selector for non-SVG files — plain paths are auto-detected as images.
  2. Verify the file actually is the claimed format (file(1) / magic bytes) and re-export to PNG/JPEG if it is TIFF/BMP/HEIC.
  3. Re-download or re-save corrupted/truncated images.
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/b0dfcbf38f74a0c8. Report an issue: GitHub.