An attachment that cannot be read says so instead of 500ing

FixMediaService
Shipped
August 27, 2026 at 7:03 AM UTC
Author
Kamo
Commit
9d70283

The imaging proxy already answers 410 for revoked access and for a removed message, but let openRange's IOException escape uncaught — so the one case where the bytes are simply absent became a blank 500. A browser's <audio>/<video> cannot render a 500; it gets one bit and latches on it, which is why a member reported an attachment that "sent" but whose play button did nothing, with no message anywhere. Three changes. The row is asked first: ImgDat.isMissing is false only once the bytes are durably written, so a missing row is answered 410 without a MinIO round trip at all. Storage failures are then split — ObjectNotStoredException to 410, anything else to 503 — so a MinIO blip reads as "try again" rather than as a file the member has permanently lost. And HEAD now actually consults storage. It used to answer 200 from the row's metadata, which made it worse than useless for the one question worth asking it: a client probing to learn whether a failed element is gone or merely unlucky was told the file was fine and then handed a 410 on the GET. A zero-length range costs one stat and settles it honestly. SystemBugController gets the same split. MediaController's outbound path already degraded to text, and now logs which of the two happened.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing