I am setting up a job to loop through a list of linked servers and execute a specific query against each one. I am trying to execute the query inside a TRY-CATCH block so if there's a problem with one particular server I can log it but then carry on with the other servers.

The query I'm executing inside the loop looks something like this:

```
BEGIN TRY
    SELECT *
    FROM OPENQUERY([server1], 'SELECT 1 AS c;');
END TRY
BEGIN CATCH
    SELECT ERROR_NUMBER(), ERROR_MESSAGE();
END CATCH;

PRINT 'We got past the Catch block!';

```

If there is a problem connecting to the server the code just fails immediately and doesn't transfer to the `CATCH` block. If the server connects but there is an error in the actual query, e.g. divide by zero, then this is caught as expected by the `CATCH` block.

For example, I created a linked server to a name that I know doesn't exist. When executing the above I just get:

```
OLE DB provider "SQLNCLI" for linked server "nonserver" returned message 
    "Login timeout expired".
OLE DB provider "SQLNCLI" for linked server "nonserver" returned message 
    "An error has occurred while establishing a connection to the server. 
    When connecting to SQL Server 2005, this failure may be caused by the 
    fact that under the default settings SQL Server does not allow remote
    connections.".
Msg 53, Level 16, State 1, Line 0
Named Pipes Provider: Could not open a connection to SQL Server [53].

```

I've read BOL on `TRY-CATCH` and know that it won't catch level 20+ errors that break the connection but this doesn't seem to be the case (this is only level 16).

Does anyone know why these errors aren't caught correctly?