can1357/oh-my-pi · error · ImageInputTooLargeError

Image file too large: ${formatBytes(source.byteLength)} exce

Error message

Image file too large: ${formatBytes(source.byteLength)} exceeds ${formatBytes(maxBytes)} limit.

What it means

After the stat-based size check, loadSvgImageInput re-checks the bytes actually read from disk and throws ImageInputTooLargeError if the buffer exceeds maxBytes — defense in depth catching size changes between stat and read (file grew concurrently, or compressed .svgz content differs).

Source

Thrown at packages/coding-agent/src/utils/image-loading.ts:489

		excludeWebP: options.excludeWebP,
	});
}

/** Rasterizes an explicitly selected local SVG/SVGZ into a vision-model image input. */
export async function loadSvgImageInput(options: LoadImageInputOptions): Promise<LoadedImageInput | null> {
	const resolvedPath = options.resolvedPath ?? resolveReadPath(options.path, options.cwd);
	const extension = path.extname(resolvedPath).toLowerCase();
	if (extension !== ".svg" && extension !== ".svgz") return null;

	const maxBytes = options.maxBytes ?? MAX_IMAGE_INPUT_BYTES;
	const stat = await Bun.file(resolvedPath).stat();
	if (stat.size > maxBytes) {
		throw new ImageInputTooLargeError(stat.size, maxBytes);
	}

	const source = await fs.readFile(resolvedPath);
	if (source.byteLength > maxBytes) {
		throw new ImageInputTooLargeError(source.byteLength, maxBytes);
	}

	let png: Uint8Array;
	try {
		png = await rasterizeSvg(source, SVG_IMAGE_MAX_EDGE_PX, SVG_IMAGE_MAX_EDGE_PX);
	} catch (error) {
		const message = error instanceof Error ? error.message : String(error);
		throw new Error(`Could not rasterize SVG: ${message}`);
	}

	return loadInMemoryImageInput({
		image: {
			type: "image",
			data: Buffer.from(png.buffer, png.byteOffset, png.byteLength).toString("base64"),
			mimeType: "image/png",
		},
		resolvedPath,
		textNotePrefix: "Read SVG file",

View on GitHub (pinned to 9690622007)

Solutions

  1. Minify the SVG and retry after the source stops changing.
  2. Ensure the SVG file is fully written (await the download/build step) before loading.
  3. Raise maxBytes if legitimately large SVGs are expected.
  4. Load from a stable copy (write to a temp file and load that) rather than a live output path.

Example fix

// before: await loadImageInput(buildDir + "/icon.svgz"); // may still be growing  // after: await buildComplete; then await loadImageInput(buildDir + "/icon.svgz");
Defensive patterns

Strategy: validation

Validate before calling

const bytes = await Bun.file(svgPath).bytes(); if (bytes.byteLength > maxBytes) throw new Error(`SVG bytes ${bytes.byteLength} exceed ${maxBytes}`);

Try / catch

try { const img = await loadImageInput(svgPath); } catch (err) { if (err instanceof ImageInputTooLargeError) { await Bun.write(stableCopy, await Bun.file(svgPath).arrayBuffer()); return loadImageInput(stableCopy); } throw err; }

Prevention

When it happens

Trigger: Calling the SVG loading path when fs.readFile returns more bytes than maxBytes even though the earlier stat passed — file mutated between stat and read, or size reported inconsistently for compressed svgz content.

Common situations: TOCTOU on a file being written concurrently (build output, download still in progress); .svgz files whose content balloons past the limit.

Related errors


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