Completely agree. The server/client example in the post was just one example of a program not being able to make progress, you’ve just gave another which cannot be solved the same way, and I would bet there are many more that they will be discovering over time. IMO when async is used, concurrency needs to be ensured.
It depends on the API. If the only way to obtain the result of the asynchronous dispatch is a synchronous operation on a completion queue, then there are no cases where a single-threaded implementation will break, other than not providing the performance.
However, we can argue that if there is only a synchronous operation to collect the result, then it's not truly async. Asynchrony should mean not only that we can initiate a request without waiting for the result, but that the completion can happen at any time.