A teammate declares `throws IOException` on a method three layers above where the exception is actually thrown, and every intermediate caller does the same because "that's what the compiler wants." What's actually wrong with reflexively propagating checked exceptions, and what rule should decide checked versus unchecked instead?
Checked exceptions were designed for recoverable conditions the caller could actually do something about; unchecked ones were for programming errors. The problem here is that none of the three intermediate layers can do anything useful with an IOException either — they don't know how to retry a file read or substitute a default, so throws IOException just climbs the call stack, forcing every layer in between to either declare it too or wrap it in a try/catch that does nothing but rethrow. That's not the compiler protecting anyone; it's ceremony. The rule that actually decides it: throw unchecked, unless the immediate caller can reasonably recover and you specifically want the compiler to force them to think about it — which is rare enough that most services standardize on unchecked exceptions for almost everything, the same way Spring wraps SQLException into unchecked DataAccessException and Hibernate and Jackson throw unchecked throughout.