Assuming you want your code to do different things according to whether an error occurs or not, you have basically three options:
1) Make this explicit everywhere in the code (C-style error return value checking). The main perceived disadvantage is that it's verbose.
2) Use non-local control flow to separate error-handling code from the "usual path" (exceptions). The main perceived disadvantage is keeping track of all the places your code can go next, especially if documented interfaces don't always list them all. Java's experiment with checked exceptions to "deal with" the latter issue weren't entirely successful either.
3) Sit on errors until "later" (IEEE-style sticky error bits and quiet NaNs, C++ error flags on streams), and check them only when convenient for the caller. The main perceived disadvantage is that setting and clearing errors requires careful use by everyone, and also that information available at the site of the error may be lost by the time it's handled.
Take your pick. (1) looks bloated and complex, and newbies mess it up by not checking for errors properly, but each line of code is easy to reason about. (2) looks small and simple, but each line of code might cause a jump to who-knows-where, so newbies mess it up by not implementing exception guarantees properly, and everyone sometimes catches exceptions in the wrong places or not at all. (3) is great when designed well, but you never know which of several possibilities each line of code is actually doing, so in a UB-rich environment like C++ that's easy to mess up too.
I think the underlying problem is basically hard: handling errors explicitly increases the branches in your code. Handling errors quietly increases the amount of state that you need to reason about, in a particular bit of code.
Exceptions also have the "is it truly exceptional?" problem. You could prevent exceptions from causing confusing control flow, by throwing them only in cases that your entire program can't recover from. But then you can't use them for errors which are recoverable from the POV of your program but not from the POV of the subsystem, so for those cases you fall back to the disadvantages of either (1) or (3).