catch.ME returns incorrect line number for error

3 views (last 30 days)
hi team
I have a script to download stock data and then do some analysis. The entire script is working fine except one little issue. I have try-catch function in my script to help me continur with stock analysis when error occurs. However when I use fprintf(ME.stack(1).line) to tell me the error location (line number) it return completely incorrect line numbers. My script has the following:
%% - to break the script in blocks for ease of use
... - to break codes in multiple lines for better readability
multiple For, If loops.
Due to sensitive info I have removed my codes but have created a structure of my script and attached here. If anyone can please help me understand why catch.ME returns incorrect line number it would be great.
Within try catch block - My codes has only two lines within try and catch block that needs try and catch (i.e., try, catch error and skip that iteration), other codes within the block just need to get skipped when error occurs. Is there a way in try catch function that we can tell what lines to apply try and catch and for the rest of the codes it throws an error and stop?
Summary - Try catch is working fine, doing what it needs to do except returning correct line number where error occured. I need help with this please.
My code has Me.stack(1).line, I noticed on matlab Q&A forum someone mentioning using Me.stack(end).line. Does this make any difference?
Regards
Amit
  2 Comments
Walter Roberson
Walter Roberson on 23 Feb 2025
Is it possible that your script is LiveScript ?
Amit Patel
Amit Patel on 23 Feb 2025

Hi Walter. No it is not a live script. All sorted. I changed my code from Me.stack(1).line to Me.stack(end).line

Now it shows the correct line number when error occurs. Cheers.

Sign in to comment.

Accepted Answer

dpb
dpb on 23 Feb 2025
Edited: dpb on 23 Feb 2025
"....except returning correct line number where error occured."
When MATLAB throws an error in the try section of a try, catch block, the system will generate an MException object. The code in the try block after the line causing the error is skipped and execution immediately resumes at the beginning of the catch section. The .stack property of the ME object is a variably-sized Nx1 struct array, the size of N being dependent upon the depth of the call stack at the time the error is thrown. Thus, N is dependent upon how many levels of function call there have been from the inception of the code to the point at which the error is generated; ME.stack(1) element will, therefore, be the actual code line/function that did create the error, but this may be in internal MATLAB code, not necessarily your code that called a MATLAB function that may, in turn, have called several more before actually triggering the error.
Without the actual code to look at, it's essentially impossible to answer definitively, but if the point is in a loop to skip an iteration in a loop if a read fails, then more than likely all that is needed is something like
d=dir('SomeWildCardPattern*.ext'); % get a list of files to process
for i=1:numel(d) % process each in turn
try
data=readtable(fullfile(d(i).folder,d(i).name)); % read the file
catch ME % something wrong with the file
contine % so skip it, go on to next
end
% process good file here...
try
result=doanalysis(data); % whatever needs doing
catch ME
continue % something went wrong, skip to next
end
end
instead of what would seem to be more like your case based on your problem description
d=dir('SomeWildCardPattern*.ext');
for i=1:numel(d)
try
data=readtable(fullfile(d(i).folder,d(i).name)); % read the file
result=doanalysis(data);
catch ME
% now try to figure out which line it was that errored and fixup
% depending on that...not the way to go.
...
end
end
The processing function could have its error handling internally to it where it may iterate over rows/variables in another loop, but skipping the analysis if there is a missing variable or row with bad data, etc., so it just skips a given observation/variable combination rather than the whole file. It's almost never a requirement to try to parse the call stack to be able to handle the exception if the handling blocks are correctly defined; as you've seen, if the code actually fails inside an internal MATLAB routine, the call stack will have that in its list, but it won't necessarily be the line in your code itself that caused the exception; trying to get at that by code is a pain and certainly the depth being a constant would not be reliable nor maintainable; any change you made to your code could/would change that depth which might be variable as well, depending upon just what the errors might be.
IF you were adamant on trying to go that route, I believe what you would have to do is to iterate through the .stack array and search for the last line for which the .name field matches your calling function; a lot of coding and debugging undoubtedly to get it to work reliably where if by propertly structuring the code it is, almost certainly, not needed.
  2 Comments
dpb
dpb on 23 Feb 2025
ADDENDUM:
"never a requirement to try to parse the call stack to be able to handle the exception ..."
OTOH, it CAN be useful to compare the error .identifier or .message property if it is a common error that occurs that know how to hadle. That doesn't need to parse the call stack...
Amit Patel
Amit Patel on 23 Feb 2025
Edited: Amit Patel on 23 Feb 2025

Hi dpb. Thank you. All sorted. I changed my code from Me.stack(1).line to Me.stack(end).line

Now it shows the correct line number when error occurs. Cheers.I have no idea what would be the mechanism of stake(1) and stake(end) but seems like now it shows correct line number.

I will keep your solution saved if I face issues in the future. Appreciated your help.

Sign in to comment.

More Answers (0)

Categories

Find more on Programming Utilities in Help Center and File Exchange

Products


Release

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!