{"record":{"id":"46c0f8602a596f2a","repo":"paperclipai/paperclip","slug":"heif-dimensions-could-not-be-verified","errorCode":null,"errorMessage":"HEIF dimensions could not be verified","messagePattern":"HEIF dimensions could not be verified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/photon/media.ts","lineNumber":70,"sourceCode":"          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;\n  if (HEIF_CONTENT_TYPES.has(contentType)) return validateHeifDimensions(body);\n  const metadata = await sharp(body, {\n    limitInputPixels: MAX_PIXELS,\n    failOn: \"error\",\n  }).metadata();\n  if (\n    !metadata.width ||\n    !metadata.height ||\n    metadata.width * metadata.height * (metadata.pages ?? 1) > MAX_PIXELS\n  )\n    throw new Error(\"Decoded image exceeds the pixel limit\");","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/photon/media.ts#L52-L88","documentation":"After walking all boxes, validateHeifDimensions checks that it saw an ftyp box with a recognized HEIF brand (heic/heix/hevc/hevx/mif1/msf1) and at least one ispe dimensions box. It throws when either is missing, meaning the bytes are not a verifiable HEIF file despite the declared content type — a guard against mislabeled or malformed containers reaching the native decoder.","triggerScenarios":"Calling validatePhotonImage/photonHeifPreview with HEIF content types on a body that lacks an ftyp box with a HEIC/HEIF brand, or has no ispe boxes (e.g. a JPEG renamed to .heic, a bare ISO-BMFF container without image spatial extents, or encrypted/drm HEIF).","commonSituations":"Clients setting Content-Type: image/heic based on file extension alone; Apple .heic files with unusual brand sets; renamed JPEG/PNG files; minimal HEIF containers that carry metadata but no image spatial extents.","solutions":["Send correct bytes: re-encode the file as a genuine HEIF (heif-enc) or fix the client to declare the true content type (e.g. image/jpeg for a renamed JPEG).","On the server, sniff magic bytes yourself before choosing the validation path: check for ftyp at offset 4 and map brands to the real type.","Fall back to validatePhotonImage with the detected (not declared) content type.","Reject with 415 Unsupported Media Type and a message asking the user to re-export the image."],"exampleFix":"// before\nawait validatePhotonImage(body, 'image/heic'); // trust the header\n// after\nconst realType = sniffImageType(body); // reads magic bytes\nif (realType !== 'image/heic')\n  return await validatePhotonImage(body, realType);\nawait validatePhotonImage(body, 'image/heic');","handlingStrategy":"validation","validationCode":"export function looksLikeHeif(body: Buffer): boolean {\n  if (body.length < 12 || body.toString('ascii', 4, 8) !== 'ftyp') return false;\n  return /heic|heix|hevc|hevx|mif1|msf1/.test(body.toString('ascii', 8, Math.min(body.length, 40)));\n}","typeGuard":"function isHeifMagic(body: Buffer): boolean {\n  return body.length >= 12 && body.toString('ascii', 4, 8) === 'ftyp' &&\n    /heic|heix|hevc|hevx|mif1|msf1/.test(body.toString('ascii', 8, 12));\n}","tryCatchPattern":"try {\n  await validatePhotonImage(body, declaredType);\n} catch (err) {\n  if (err instanceof Error && err.message === 'HEIF dimensions could not be verified') {\n    const real = sniffImageType(body);\n    if (real && real !== declaredType) return validatePhotonImage(body, real);\n    return respond(415, 'file is not a valid HEIF image');\n  }\n  throw err;\n}","preventionTips":["Derive Content-Type from magic bytes, never from file extension","Sniff ftyp brands server-side before choosing the HEIF validation path","Reject renamed files with 415 early instead of deep validation","Keep client upload libraries from defaulting unknown types to image/heic"],"tags":["image","heif","content-type-mismatch","validation"],"backgroundTag":"unexpected-response-shape","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"}