paperclipai/paperclip · error
HEIF metadata nesting is too deep
Error message
HEIF metadata nesting is too deep
What it means
validateHeifDimensions parses the ISO-BMFF box tree of a HEIF/HEIC buffer with a bounded recursive visit() before any native decoder runs. If recursion depth exceeds 8 (meta/iprp/ipco containers nested too deeply) it throws "HEIF metadata nesting is too deep". This is a hardening limit against maliciously crafted deeply nested files that could exhaust the parser or decoder.
Solutions
- Reject the upload — this limit is intentional; re-encode the image with standard tooling (e.g. sips, ImageMagick, libheif) to flatten metadata.
- Strip metadata from the HEIF before re-submitting (exiftool -all= or heif-convert/re-encode).
- Verify the file opens in a standard viewer; if not, the file is likely corrupt or malicious — do not process.
- If legitimate depth is truly required, raise the depth limit in media.ts with a code change and fresh security review.
Example fix
// shell re-encode before upload // before: file.heic with 10-level nested meta boxes // after: magick file.heic -strip flattened.heic
Defensive patterns
Strategy: validation
Validate before calling
// heuristic pre-check: reject implausibly large HEIF metadata before server-side validation
function plausibleHeifSize(buf: Buffer): boolean {
return buf.length > 0 && buf.length <= MAX_ATTACHMENT_BYTES && buf.toString("ascii", 4, 8) === "ftyp";
} Type guard
function looksLikeHeif(b: Buffer): b is Buffer {
return b.length >= 12 && b.toString("ascii", 4, 8) === "ftyp";
} Try / catch
try {
validateHeifDimensions(body);
} catch (e) {
if (e instanceof Error && e.message === "HEIF metadata nesting is too deep") {
return rejectUpload("HEIF file has unsafe metadata nesting; re-encode the image");
}
throw e;
} Prevention
- Re-encode HEIC/HEIF from untrusted sources with mainstream tooling before upload.
- Strip extraneous metadata (exiftool -all=) from images originating outside standard cameras.
- Never attempt to bypass depth limits on user-supplied files — treat deep nesting as hostile.
- Keep uploads within MAX_ATTACHMENT_BYTES to fail fast on other guards.
When it happens
Trigger: Calling validateHeifDimensions (directly or via validatePhotonImage/photonHeifPreview) on a HEIF buffer whose meta/iprp/ipco box nesting is deeper than 8 levels — interactions.ts-independent, media.ts:22.
Common situations: Uploading a crafted/fuzzed HEIC file; unusual but legitimate deeply nested HEIF metadata from exotic camera tooling; a file mislabeled as image/heic that happens to nest boxes deeply.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- HEIF box exceeds file bounds
- HEIF file type is missing
- Invalid HEIF box length
- Invalid HEIF box structure
- Invalid HEIF image dimensions
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/8602d6b6d96f71f1.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/photon/media.ts:22
import { MAX_ATTACHMENT_BYTES } from "../../attachment-types.js";
const require = createRequire(import.meta.url);
const MAX_PIXELS = 50_000_000;
export const HEIF_CONTENT_TYPES = new Set([
"image/heic",
"image/heif",
"image/heic-sequence",
"image/heif-sequence",
]);
/** Validate bounded ISO-BMFF structure before invoking any native decoder. */
export function validateHeifDimensions(body: Buffer): void {
let boxes = 0;
let dimensions = 0;
let totalPixels = 0;
let branded = false;
const visit = (start: number, end: number, depth: number) => {
if (depth > 8) throw new Error("HEIF metadata nesting is too deep");
for (let at = start; at < end; ) {
if (++boxes > 4096 || end - at < 8)
throw new Error("Invalid HEIF box structure");
let size = body.readUInt32BE(at);
const type = body.toString("ascii", at + 4, at + 8);
let header = 8;
if (size === 1) {
if (end - at < 16) throw new Error("Invalid HEIF box length");
const extended = body.readBigUInt64BE(at + 8);
if (extended > BigInt(body.length))
throw new Error("HEIF box exceeds file bounds");
size = Number(extended);
header = 16;
} else if (size === 0) size = end - at;
if (size < header || at + size > end)
throw new Error("HEIF box exceeds file bounds");
const content = at + header;
if (type === "ftyp") {View on GitHub (pinned to 3f1d897a7c)