I believe that what is happening here is that in your first example, the
batch is failing with a syntax error:
Msg 208, Level 16, State 1, Line 1
Invalid object name 'nonexistingtableorfunction'.
This means that it failed at compile time and never executed. Since it
never executed, the try / catch had no chance to do anything.
In your second example, the called routine got the same error as above and
However, in this case the calling routine is running just fine and the try /
catch sees that the called routine got an error.
At least, that is what it looks like to me.