can1357/oh-my-pi · error · ImageInputTooLargeError

Image file too large: ${formatBytes(inputBytes)} exceeds ${f

Error message

Image file too large: ${formatBytes(inputBytes)} exceeds ${formatBytes(options.maxBytes)} limit.

What it means

loadInMemoryImageInput measures the base64 image payload size and throws ImageInputTooLargeError before decoding, so oversized images never enter the model transcript where the provider would reject the whole request.

Source

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

		return null;
	} catch (error) {
		return error instanceof Error ? error.message : String(error);
	}
}

interface LoadInMemoryImageInputOptions {
	image: ImageContent;
	resolvedPath: string;
	textNotePrefix: string;
	autoResize: boolean;
	maxBytes: number;
	excludeWebP: boolean | undefined;
}

async function loadInMemoryImageInput(options: LoadInMemoryImageInputOptions): Promise<LoadedImageInput> {
	const inputBytes = Buffer.byteLength(options.image.data, "base64");
	if (inputBytes > options.maxBytes) {
		throw new ImageInputTooLargeError(inputBytes, options.maxBytes);
	}

	// Decode before anything else: a payload that cannot be decoded is rejected
	// by the provider for the whole request, so it must fail here — where the
	// caller still has a path to act on — instead of entering the transcript.
	const decodeFailure = await imageDecodeFailureReason(options.image);
	if (decodeFailure !== null) {
		throw new InvalidImageDataError(options.resolvedPath, options.image.mimeType, decodeFailure);
	}

	let outputData = options.image.data;
	let outputMimeType = options.image.mimeType;
	let outputBytes = inputBytes;
	let dimensionNote: string | undefined;

	const shouldReencodeWebP = options.excludeWebP === true && options.image.mimeType === "image/webp";
	if (options.autoResize || shouldReencodeWebP) {
		try {

View on GitHub (pinned to 9690622007)

Solutions

  1. Compress or downscale the image before passing it so it fits maxBytes.
  2. Raise the maxBytes option at the call site if the limit is too strict for your workflow.
  3. Convert to a more compact format (JPEG/WebP) or strip metadata to reduce bytes.
  4. Check the file size first with fs.stat and surface a friendly message before attempting the load.

Example fix

// before: await loadImageInput(path, { maxBytes: 100_000 }); // 3MB screenshot  // after: compress/downscale to a small JPEG, then await loadImageInput(path, { maxBytes: 100_000 });
Defensive patterns

Strategy: validation

Validate before calling

const bytes = Buffer.byteLength(base64, "base64"); if (bytes > maxBytes) throw new Error(`image is ${bytes} bytes, limit is ${maxBytes}`);

Try / catch

try { const img = await loadImageInput(path, { maxBytes }); } catch (err) { if (err instanceof ImageInputTooLargeError) { return resizeAndRetry(path, maxBytes); } throw err; }

Prevention

When it happens

Trigger: Passing image content whose base64 data exceeds options.maxBytes to loadInMemoryImageInput — reached via loadImageInput, loadSvgImageInput, or loadImageAttachmentInput when a file or attachment is over the configured byte limit.

Common situations: Attaching screenshots or camera photos several MB large; a caller configured with a small maxBytes; sending SVG or PNG exports from design tools without compression.

Related errors


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