Моду на коды ошибок вместо исключений ввели разработчики Rust, причём только потому, что не смогли совместить исключения и Borrow Checker. Других причин не было. Вся чушь, которую написали после: про скорость, или там надёжность с безопасностью — чистая идеологическая хрень. Написать "мы облажались, терпите" означало растерять фан-базу.
Деды программирования наелись кодов ошибок по полной задолго до нас. И, имея в тысячи раз меньше памяти и медленнее процессора, эти деды таки сделали исключения. Что ждёт rust и другие языки — наворачивание обёрток и макросов для "удобного проброса" кодов ошибок и стектрейсов наверх. И в итоге они получат те же исключения. Есть шанс, что, при нормальном метапрограммировании, получится даже круче и фичастее чем то, что сейчас разработчики компиляторов хардкодят. Например, декларативно задавать, какие операции перезапускаемые, или в конфигах описывать какие исключения обязательно должны пойти в лог. Или автоматическое сохранение и передача всяких Trace-Id.
Языки, у которых макросов и метапрограммирования нет, и при этом всё сделано на кодах ошибок — пригодны только для мелких проектов, и, даже если будут какое-то время популярны на хайпе, в итоге вымрут. Просто потому, что на языках, где писать легче, кода напишут больше. А больше кода — это больше проектов в которых нужны программисты, лучше подсказки ИИ, больше информации в интернете, и больше вакансий. С учётом этого, тратить время на языки без исключений и метапрограммирования, можно только за счёт работодателя, и за очень большие деньги. Во всех остальных случаях, любой хайп вокруг них можно смело игнорить.
S>А ведь было же хорошее решение — т.н. проверяемые исключения в Java. Когда компилятор требовал проверки того или иного исключения, но так же была возможно обернуть в RuntimeException, если оно утратило смысл бизнес-логики или ожидаемого 
Хельсберг очень подробно когда-то объяснял, почему эту фичу в C# не потащили. Кмк, что реально нужно — возможность указать no throw, и throws(список). Чтобы те, кому нужна железная уверенность что всё перехватывается, могли желаемую надёжность получить. А те, кому достаточно вывести на экран сообщение "коннекта к базе нет", могли писать db.Connect() и радоваться что единственный try/catch в main решает все их проблемы.