paperclipai/paperclip · error
HEIF dimensions could not be verified
Error message
HEIF dimensions could not be verified
What it means
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.
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.
Example fix
// before await validatePhotonImage(body, 'image/heic'); // trust the header // after const realType = sniffImageType(body); // reads magic bytes if (realType !== 'image/heic') return await validatePhotonImage(body, realType); await validatePhotonImage(body, 'image/heic');
Defensive patterns
Strategy: validation
Validate before calling
export function looksLikeHeif(body: Buffer): boolean {
if (body.length < 12 || body.toString('ascii', 4, 8) !== 'ftyp') return false;
return /heic|heix|hevc|hevx|mif1|msf1/.test(body.toString('ascii', 8, Math.min(body.length, 40)));
} Type guard
function isHeifMagic(body: Buffer): boolean {
return body.length >= 12 && body.toString('ascii', 4, 8) === 'ftyp' &&
/heic|heix|hevc|hevx|mif1|msf1/.test(body.toString('ascii', 8, 12));
} Try / catch
try {
await validatePhotonImage(body, declaredType);
} catch (err) {
if (err instanceof Error && err.message === 'HEIF dimensions could not be verified') {
const real = sniffImageType(body);
if (real && real !== declaredType) return validatePhotonImage(body, real);
return respond(415, 'file is not a valid HEIF image');
}
throw err;
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- HEIF decoded image exceeds the pixel limit
- HEIF image collection exceeds the pixel limit
- Image bytes do not match the declared content type
- Decoded image exceeds the pixel limit
- HEIF exceeds the attachment byte limit
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/46c0f8602a596f2a.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/photon/media.ts:70
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;
if (HEIF_CONTENT_TYPES.has(contentType)) return validateHeifDimensions(body);
const metadata = await sharp(body, {
limitInputPixels: MAX_PIXELS,
failOn: "error",
}).metadata();
if (
!metadata.width ||
!metadata.height ||
metadata.width * metadata.height * (metadata.pages ?? 1) > MAX_PIXELS
)
throw new Error("Decoded image exceeds the pixel limit");View on GitHub (pinned to 3f1d897a7c)