paperclipai/paperclip · error
HEIF image collection exceeds the pixel limit
Error message
HEIF image collection exceeds the pixel limit
What it means
While validating a HEIF container, validateHeifDimensions accumulates totalPixels across all ispe boxes and counts dimensions. It throws when the collection totals exceed MAX_PIXELS*3 (150MP) or when more than 512 distinct image dimensions are declared — i.e. the file is a multi-image HEIC sequence or collection whose aggregate decoded size would be too large. This bounds worst-case decode cost across all embedded images, not just the largest one.
Solutions
- Ask the user to send a single still image (extract the key frame, e.g. ffmpeg -i in.heic -frames:v 1 out.jpg) instead of a Live Photo / sequence.
- Strip non-essential derivative images from the HEIF before upload (e.g. heif-convert or exiftool to reduce items).
- If the product needs sequences, split the collection into individual images and validate each separately.
- Raise MAX_PIXELS*3 or the 512-dimension cap in media.ts if the workload legitimately requires larger collections.
Example fix
// before await photonHeifPreview(livePhotoHeic); // sequence -> throws // after const still = await extractKeyFrame(livePhotoHeic); // single-image HEIC/JPEG await photonHeifPreview(still);
Defensive patterns
Strategy: validation
Validate before calling
export function isBoundedHeifCollection(dimensions: Array<{w:number;h:number}>): boolean {
const total = dimensions.reduce((s, d) => s + d.w * d.h, 0);
return dimensions.length <= 512 && total <= 50_000_000 * 3;
} Type guard
function isStillHeic(brandString: string): boolean {
return /mif1|heic|heix/.test(brandString) && !/msf1|hevc-seq|sequence/.test(brandString);
} Try / catch
try {
await photonHeifPreview(heicBuffer);
} catch (err) {
if (err instanceof Error && err.message === 'HEIF image collection exceeds the pixel limit') {
return respond(413, 'Live Photo/sequence too large; send a single still image');
}
throw err;
} Prevention
- Prefer single-image HEIC over heic-sequence uploads
- Extract the key frame from Live Photos client-side before sending
- Limit embedded thumbnails/derivatives in generated HEIF files
- Track aggregate pixel budget, not just per-image size, in your own upload checks
When it happens
Trigger: Uploading a burst/sequence HEIC (image/heic-sequence), a photo with many derivatives/thumbnails, or any HEIF whose sum of ispe pixel counts exceeds 150,000,000 or which declares more than 512 ispe boxes.
Common situations: iPhone Live Photos and burst photos stored as HEIC sequences; users bulk-embedding many images into one HEIF container; live-photo imports from shared albums.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
- HEIF decoded image exceeds the pixel limit
- HEIF dimensions could not be verified
- Decoded image exceeds the pixel limit
- HEIF exceeds the attachment byte limit
- Image bytes do not match the declared content type
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/b50a792a9e150a41.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/photon/media.ts:59
if (size < header + 8) throw new Error("HEIF file type is missing");
const brands = body.toString("ascii", content, at + size);
branded = /heic|heix|hevc|hevx|mif1|msf1/.test(brands);
} else if (type === "ispe") {
if (size !== header + 12)
throw new Error("Invalid HEIF image dimensions");
const width = body.readUInt32BE(content + 4);
const height = body.readUInt32BE(content + 8);
if (
!width ||
!height ||
width > 16_384 ||
height > 16_384 ||
width * height > MAX_PIXELS
)
throw new Error("HEIF decoded image exceeds the pixel limit");
totalPixels += width * height;
if (totalPixels > MAX_PIXELS * 3 || ++dimensions > 512)
throw new Error("HEIF image collection exceeds the pixel limit");
} else if (["meta", "iprp", "ipco"].includes(type)) {
visit(content + (type === "meta" ? 4 : 0), at + size, depth + 1);
}
at += size;
}
};
if (!body.length || body.length > MAX_ATTACHMENT_BYTES)
throw new Error("HEIF exceeds the attachment byte limit");
visit(0, body.length, 0);
if (!branded || !dimensions)
throw new Error("HEIF dimensions could not be verified");
}
export async function validatePhotonImage(
body: Buffer,
contentType: string,
): Promise<void> {
if (!contentType.startsWith("image/")) return;View on GitHub (pinned to 3f1d897a7c)