Another idea using Extended Events.
Create an extended events session to catch errors
CREATE EVENT SESSION [Track_Errors] ON SERVER
ADD EVENT sqlserver.error_reported(
ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_name,sqlserver.is_system,sqlserver.server_instance_name,sqlserver.server_principal_name,sqlserver.sql_text))
ADD TARGET package0.event_file(SET filename=N'D:\some_path\track_errors',max_file_size=(50),max_rollover_files=(5))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=ON)
GO
ALTER EVENT SESSION [Track_Errors] ON SERVER STATE = START
Then in your nested stored procedures, use RAISEERROR or THROW to print out the name of the stored procedure in the message column of extended events.
RAISERROR ('sp_test_nested_error', 16, 1) WITH NOWAIT
THROW 50000, N'sp_test_nested_error', 1;
Here are the two stored procedures I used to test
-- nested stored procedure
CREATE procedure [dbo].[sp_test_nested_error]
AS
BEGIN TRY
-- Generate a divide-by-zero error
SELECT
1 / 0 AS Error;
END TRY
BEGIN CATCH
THROW 50000, N'sp_test_nested_error', 1;
END CATCH;
GO
-- parent stored procedure
CREATE procedure [dbo].[sp_test_proc]
AS
exec sp_test_nested_error
GO
And the resulting extended events output
