Hell yeah. I typed in my first C program, a terminal emulator, from a 1984 issue of Byte magazine. It was painful seeing how 5 lines of real logic were intertwined with 45 lines of error handling logic that, in the end, did what exceptions did for free -- it was a formative experience for me as a programmer and when I saw exceptions in Java in 1995 (still in beta) they made me so happy.
In the async case you can pass the Exception as an object as opposed to throwing it but you're still left with the issue that the failure of one "task" in an asynchronous program can cause the failure of a supertask which is comprised of other tasks and handling that involves some thinking. That's chess whereas the stuff talked about in that article is Tic-Tac-Toe in comparison.
Yeah, I agree in the async case. What I do there is wrapped the async code in its own global error handler, so to speak. That handler is logging to something that the outer process can get-last-error from.
But I can get away with this also because I don't write async heavy code. My web applications are thread-per-request (Java). This fits 99% of the needs of business code, whose processing nature is mostly synchronous.