Действительно исключительная ситуация (отказ, по предусловию, по переполнению и проч.) должна обрабатываться на одном уровне, в одном месте в процессе. Для этого достаточно библиотечного Try. Например, на уровне главного цикла встроенного или серверного приложения. В случае отказа именно на этом уровне принимается решение о логике восстановления системы.
Рассыпанными хаотично по программе TRY проблема живучести приложения не решается; без единой логики восстановления (какое состояние перманентно, какое теряется при сбое - и идёт перезапуск задачи с чистого листа...).
Кроме того, всегда говорю - представьте случай с сотнями параллельных задач (а даже для микроконтроллеров есть методы такого программирования; например система "Рефлекс" Евгения Зюбина).
Исключение кидать по стеку просто некому.

А ситуации, которые происходят не аварийно, а штатно, периодично (например, файл не найден или удалённый сервер не доступен) - это не предмет для исключений. Хотя иногда можно и их использовать, опять же, библиотечного Try достаточно (например, написали сценарий, обращающийся к неск. удалённым серверам, которые бывают недоступны, что-то снимающий с них - протаскивать коды успеха не хочется, шпигуем ASSERT-ами, и вешаем один Try на весь сценарий, плюс цикл - долбить, пока не будет успеха).