{"record":{"id":"e765c39f35bf850d","repo":"paperclipai/paperclip","slug":"heif-file-type-is-missing","errorCode":null,"errorMessage":"HEIF file type is missing","messagePattern":"HEIF file type is missing","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/photon/media.ts","lineNumber":41,"sourceCode":"    for (let at = start; at < end; ) {\n      if (++boxes > 4096 || end - at < 8)\n        throw new Error(\"Invalid HEIF box structure\");\n      let size = body.readUInt32BE(at);\n      const type = body.toString(\"ascii\", at + 4, at + 8);\n      let header = 8;\n      if (size === 1) {\n        if (end - at < 16) throw new Error(\"Invalid HEIF box length\");\n        const extended = body.readBigUInt64BE(at + 8);\n        if (extended > BigInt(body.length))\n          throw new Error(\"HEIF box exceeds file bounds\");\n        size = Number(extended);\n        header = 16;\n      } else if (size === 0) size = end - at;\n      if (size < header || at + size > end)\n        throw new Error(\"HEIF box exceeds file bounds\");\n      const content = at + header;\n      if (type === \"ftyp\") {\n        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\");","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/photon/media.ts#L23-L59","documentation":"An ftyp (file type) box must carry at least a major brand (4 bytes) beyond its 8-byte header, i.e. size >= header + 8 (4 brand + typically minor version). If an ftyp box is smaller, the walker throws \"HEIF file type is missing\" because the HEIF brand information needed to confirm heic/heif compatibility cannot be read.","triggerScenarios":"A buffer containing an ftyp box with size < 16 bytes (header 8 + fewer than 8 content bytes) encountered during validateHeifDimensions (media.ts:40-41).","commonSituations":"Hand-crafted or corrupted file with a stub ftyp; a container renamed to .heic that is not really HEIF; fuzzed input probing brand detection.","solutions":["Reject the file — a valid HEIF always has a proper ftyp box; re-export from the source app.","Verify with `ffprobe` or `file` that the file is genuinely HEIF/HEIC with readable brands.","Re-encode to HEIC with sips/ImageMagick/libheif if the source is a convertible format.","If malicious, keep blocked: the check gates downstream brand detection."],"exampleFix":"// before: stub ftyp box (size 12)\n// after: re-encode\nmagick input.png -quality 90 output.heic","handlingStrategy":"validation","validationCode":"function hasProperFtyp(buf: Buffer): boolean {\n  if (buf.length < 16 || buf.toString(\"ascii\", 4, 8) !== \"ftyp\") return false;\n  return buf.readUInt32BE(0) >= 16;\n}","typeGuard":"function isBrandedHeif(b: Buffer): boolean {\n  if (b.length < 16 || b.toString(\"ascii\", 4, 8) !== \"ftyp\") return false;\n  if (b.readUInt32BE(0) < 16) return false;\n  return /heic|heix|hevc|hevx|mif1|msf1/.test(b.toString(\"ascii\", 8, b.readUInt32BE(0)));\n}","tryCatchPattern":"try {\n  validateHeifDimensions(body);\n} catch (e) {\n  if (e instanceof Error && e.message === \"HEIF file type is missing\") {\n    return rejectUpload(\"Not a valid HEIF file (missing brand data); re-export the image\");\n  }\n  throw e;\n}","preventionTips":["Verify magic bytes match the declared content type before HEIF validation.","Never rename non-HEIF containers to .heic; convert properly.","Client-side check with `file image.heic` before upload.","Re-encode with sips/ImageMagick/libheif when converting from other formats."],"tags":["heif","isobmff","malformed-file","input-validation"],"backgroundTag":"invalid-argument-format","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"}