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

  1. 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.
  2. Strip non-essential derivative images from the HEIF before upload (e.g. heif-convert or exiftool to reduce items).
  3. If the product needs sequences, split the collection into individual images and validate each separately.
  4. 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

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


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)