- Shipped
- August 27, 2026 at 6:58 AM UTC
- Author
- Kamo
- Commit
- a440534
openRange collapsed every node failure into one IOException, so a caller could do nothing with it but return 500. A browser's <img>/<video>/<audio> cannot render a 500 — it gets one bit, "failed", and latches on it — so an attachment whose object was never written answered a member's play button by going quiet. The failure reached us only because someone said "it sent but they can't play it". The two causes deserve opposite answers. Content absent is permanent and worth saying plainly; storage unreachable is transient and worth retrying. Raise ObjectNotStoredException only when the WHOLE fleet answered and every answer was NoSuchKey: a node that could not be reached might be the one holding the object, so a mix stays an ordinary IOException. Telling a member their file is permanently lost during a partial outage is the one mistake here that cannot be walked back. It extends IOException, so all seven existing call sites keep working untouched and opt into the distinction by catching it first.