If we run this code, we'll notice that, even though the Error is thrown, the code in the catch block never gets executed. This might seem strange but this is actually a totally normal and intended behavior! What's happening is that the Error is indeed thrown, but it is caught by the Task. And from that point, the Task has no way of re-throwing the Error to the function loginUser(), because the Task is running asynchronously and the function loginUser() has already finished executing! And actually the reason why this confusion was made possible is because I've made a mistake when writing this code! You see, I've declared the function loginUser() as throwing, but there's actually no call to a throwing function inside its scope. Using the keyword throws here is completely superfluous, and if I remove it we can see that the code still builds, but now we get a very clear warning that the catch block will never be executed: |