Hi Andrew

I appreciate this is an old post - I came across it when looking into the message numbers as I want to avoid using system defined numbers.

Return messages for stored procedures are poorly documented as you say.  The message for the internal error codes can be found by querying sys.messages, e.g.

select * from sys.messages where language_id = 1033 and message_id = 208

Which returns the message

Invalid object name '%.*ls'.

Not really much more helpful! 

You can wrap the SP in a TRY CATCH:

DECLARE @ReturnCode INT
 
DECLARE @Error nvarchar(MAX);

BEGIN TRY
    EXEC @ReturnCode = sp_executesql N'SELECT * FROM tblMovies'
    SELECT @ReturnCode
END TRY
BEGIN CATCH
    SET @Error =
       N'Error Number: '   + CAST(ERROR_NUMBER() AS VARCHAR(10)) + '; ' +
        'Error Severity: ' + CAST(ERROR_SEVERITY() AS VARCHAR(10)) + '; ' +
        'Error State: '    + CAST(ERROR_STATE() AS VARCHAR(10)) + '; ' +
        'Error Line: '     + CAST(ERROR_LINE() AS VARCHAR(10)) + '; ' +
        'Error Message: '  + ERROR_MESSAGE()
      RAISERROR(@Error, 0, 1) WITH NOWAIT;
END CATCH

This will give some information and allow the error to be handled.  However it won't work if you put the TRY CATCH  inside the SP! The documentation for this is here.