can1357/oh-my-pi · error · ToolError

error.message (ImageInputTooLargeError or InvalidImageDataEr

Error message

error.message (ImageInputTooLargeError or InvalidImageDataError)

What it means

When loadImageInput/loadSvgImageInput throw ImageInputTooLargeError (image exceeds size or post-decode dimension limits even after auto-resize) or InvalidImageDataError (bytes are not a decodable image), #loadImageContent converts them into ToolError with the original actionable message so the model can fix its input instead of a corrupt/oversized payload entering the transcript. Other error types propagate unchanged.

Source

Thrown at packages/coding-agent/src/tools/read.ts:882

				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);
			}
			throw error;
		}
	}

	/**
	 * Render multiple non-contiguous ranges of a local file. ACP bridge takes
	 * priority when present (editor buffer is source of truth); otherwise ranges
	 * are sliced out of `buffered` when the caller already materialized the file,
	 * and streamed independently with their own line/byte budget when it did not.
	 * Out-of-bounds ranges surface as inline notices rather than aborting the read.
	 */
	async #readLocalFileMultiRange(
		absolutePath: string,
		ranges: readonly LineRange[],
		fileSize: number,
		buffered: BufferedFileText | undefined,
		parsed: ParsedSelector,

View on GitHub (pinned to 9690622007)

Solutions

  1. Read error.message — it states whether the issue is size or decodability.
  2. Resize/re-encode the image below the byte and pixel limits, then re-read.
  3. Verify the bytes decode (open in an image viewer) — replace corrupt files.
  4. For WebP-excluded models, convert to PNG/JPEG first.

Example fix

// before
read('huge-panorama.png') // ImageInputTooLargeError even after auto-resize
// after
$ `magick huge-panorama.png -resize 2000x -quality 85 small.jpg`
read('small.jpg')
Defensive patterns

Strategy: validation

Validate before calling

// pre-check both size and decodability
import { statSync } from 'node:fs';
import { fileTypeFromBuffer } from 'file-type';
if (statSync(p).size > MAX_IMAGE_SIZE) await shrink(p);
const ft = await fileTypeFromBuffer(await Bun.file(p).bytes());
const mime = ft?.mime;
if (!mime?.startsWith('image/')) throw new Error(`${p} is not a decodable image (${mime})`);

Type guard

function isImagePayloadError(e: unknown): e is ToolError {
  return e instanceof ToolError &&
    /too large|invalid|unsupported|corrupt/i.test(e.message);
}

Try / catch

try {
  return await readTool.execute({ path: imgPath });
} catch (e) {
  if (isImagePayloadError(e)) {
    const fixed = await reencodeImage(imgPath); // resize + re-encode to JPEG
    return await readTool.execute({ path: fixed });
  }
  throw e;
}

Prevention

When it happens

Trigger: Image too large after autoResize attempts (autoResize: this.#autoResizeImages with maxBytes: MAX_IMAGE_SIZE); decode failure on corrupt bytes; WebP excluded for the active model (excludeWebP) and no fallback possible; invalid SVG markup.

Common situations: Giant panoramas that cannot be resized enough; truncated or partially-written files; text files renamed .png; model-incompatible formats (WebP to a vision model that rejects it).

Related errors


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