{"record":{"id":"b50a792a9e150a41","repo":"paperclipai/paperclip","slug":"heif-image-collection-exceeds-the-pixel-limit","errorCode":null,"errorMessage":"HEIF image collection exceeds the pixel limit","messagePattern":"HEIF image collection exceeds the pixel limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/photon/media.ts","lineNumber":59,"sourceCode":"        if (size < header + 8) throw new Error(\"HEIF file type is missing\");\n        const brands = body.toString(\"ascii\", content, at + size);\n        branded = /heic|heix|hevc|hevx|mif1|msf1/.test(brands);\n      } else if (type === \"ispe\") {\n        if (size !== header + 12)\n          throw new Error(\"Invalid HEIF image dimensions\");\n        const width = body.readUInt32BE(content + 4);\n        const height = body.readUInt32BE(content + 8);\n        if (\n          !width ||\n          !height ||\n          width > 16_384 ||\n          height > 16_384 ||\n          width * height > MAX_PIXELS\n        )\n          throw new Error(\"HEIF decoded image exceeds the pixel limit\");\n        totalPixels += width * height;\n        if (totalPixels > MAX_PIXELS * 3 || ++dimensions > 512)\n          throw new Error(\"HEIF image collection exceeds the pixel limit\");\n      } else if ([\"meta\", \"iprp\", \"ipco\"].includes(type)) {\n        visit(content + (type === \"meta\" ? 4 : 0), at + size, depth + 1);\n      }\n      at += size;\n    }\n  };\n  if (!body.length || body.length > MAX_ATTACHMENT_BYTES)\n    throw new Error(\"HEIF exceeds the attachment byte limit\");\n  visit(0, body.length, 0);\n  if (!branded || !dimensions)\n    throw new Error(\"HEIF dimensions could not be verified\");\n}\n\nexport async function validatePhotonImage(\n  body: Buffer,\n  contentType: string,\n): Promise<void> {\n  if (!contentType.startsWith(\"image/\")) return;","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/photon/media.ts#L41-L77","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait photonHeifPreview(livePhotoHeic); // sequence -> throws\n// after\nconst still = await extractKeyFrame(livePhotoHeic); // single-image HEIC/JPEG\nawait photonHeifPreview(still);","handlingStrategy":"validation","validationCode":"export function isBoundedHeifCollection(dimensions: Array<{w:number;h:number}>): boolean {\n  const total = dimensions.reduce((s, d) => s + d.w * d.h, 0);\n  return dimensions.length <= 512 && total <= 50_000_000 * 3;\n}","typeGuard":"function isStillHeic(brandString: string): boolean {\n  return /mif1|heic|heix/.test(brandString) && !/msf1|hevc-seq|sequence/.test(brandString);\n}","tryCatchPattern":"try {\n  await photonHeifPreview(heicBuffer);\n} catch (err) {\n  if (err instanceof Error && err.message === 'HEIF image collection exceeds the pixel limit') {\n    return respond(413, 'Live Photo/sequence too large; send a single still image');\n  }\n  throw err;\n}","preventionTips":["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"],"tags":["image","heif","validation","pixel-budget"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}