The "Invalid Photograph" error is a lie.
Here is the engineering nightmare: if you resize a face to exactly 200x230 pixels, the resulting JPEG is naturally going to be around 10-15 KB. It's physically impossible to hit a 20 KB floor without actually increasing the file size. Yet, every image compressor on the market is designed to shrink files. We have tools to make things smaller, but almost nothing to make a file bigger.
When you try to "compress" a file that is already under the limit, you're moving in the wrong direction. You're optimizing for a ceiling when the floor is what's killing you.
I spent some time digging into how to actually solve this without just padding the file with junk data that breaks the header. If you are hitting a minimum size requirement, you have to reverse your logic. Instead of binary-searching for the highest quality that stays under the max, you need to find the lowest quality that stays above the floor.
let lo = 0.05, hi = 1.0, best = null;
for (let i = 0; i < 20; i++) {
let mid = (lo + hi) / 2;
if (simulateSize(mid) > targetMin) {
best = mid;
hi = mid;
} else {
lo = mid;
}
}But there is a secondary, more insidious bug: the "Fake JPEG" problem.
I noticed during my post-mortem that many silent upload failures aren't about size at all—they are about MIME type mismatches. If you're on an iPhone, you're shooting HEIC. If you rename a file to .jpg or use a sloppy converter, you often end up with a file that has a JPEG extension but an underlying ISO-BMFF structure. The server expects a JPEG header, sees ftyp instead, and just drops the connection or clears the form without a single error message.
If you're building a validator or just trying to get a form to work, stop trusting the file extension. You have to inspect the actual bytes.
function isActuallyJpeg(buf) {
// Check for JPEG SOI marker
return buf[0] === 0xff && buf[1] === 0xd8;
}function checkHecFormat(buf) {
// HEIC/ISO-BMFF check: bytes 4-8 are 'ftyp'
const signature = buf.toString('ascii', 4, 8);
return signature === 'ftyp';
}
In production, shipping a file that passes the size check but has a corrupt header is a nightmare for maintainability. It's better to catch the mismatch at the client side than to let a user submit a "perfect" file that fails silently on the backend.