Errors in listener callbacks

I have an app built in MATLAB App Designer. the underlying code utlizes events and listeners. my problem is this: Whenever an error occurs in the code, the app needs to know about this. when the error occurs in the code itself, there are built in "catch" commands that notify the GUI.
However, when an error occurs in one of the listener callbacks, there is some built in mechanism that replaces the error with a warning. Instead of getting an error message we get a warning: "error occurred during execution of listener callback" and a description of the error message.
Is there a way to cancel this mechanism? to let the errors in listener callbacks become actual error messages? or maybe a way to notify the app in case of a warning? something like try catch that includes warnings?
many thanks
Nathan

 Risposta accettata

Adam Danz
Adam Danz il 31 Mag 2023
Modificato: Adam Danz il 31 Mag 2023
> Is there a way to cancel this mechanism? to let the errors in listener callbacks become actual error messages?
No, there isn't an off-switch to this behavior.
> or maybe a way to notify the app in case of a warning?
It's unclear what listeners you are refering to but I'll assume they were added by the developer of the app rather than by app-designer. One idea is to wrap the listener's callback function within a try/catch and to take some action within the catch block when there is an error. However, warnings are not caught by the try-block.
Another idea is to use lastwarn to clear the last-warning-history at the beginning of the listener's callback and then to query lastwarn again at the end of the callback to determine if a warning was thrown.
Neither of these potential solutions would catch warnings that are thrown prior to or after reaching the callback function.
lastwarn('') % clear last warning
% < function code goes here >
[msg, id] = lastwarn();
if ~isempty(msg)
% take action on warning
end

5 Commenti

Klont
Klont il 8 Feb 2024
@Adam Danz Do you know what might be the reason MATLAB treats errors in listener callbacks as warnings?
Why not let the coder decide? I wonder.
Seems straightforward enough:
  • They could type "error" if they want an error and "warning" when they want a warning.
  • Or simply use a "try/catch me" inside the listener callback and convert any error that might occur to a "warning(me.message)" to achieve the current behavior. Easy-peasy. The other way around, converting a warning to an error inside the listener callback, seems impossible.
I don't understand the point of this language design decision at all.
Do you have any insights, perhaps?
Thanks,
Jacob
Adam Danz
Adam Danz il 13 Feb 2024
> Do you know what might be the reason MATLAB treats errors in listener callbacks as warnings?
Treating errors in listener callbacks as warnings helps to maintain the stability and continuity of the event handling system. In event-driven programming, listeners respond to events such as changes in properties, user interactions, or other triggers. If an error occurs within a listener callback and it is treated as a hard error, it could interrupt the event processing flow, potentially leaving the system in an inconsistent state following an early termination.
By treating these errors as warnings, MATLAB allows the event processing to continue while also providing feedback in the form or warnings. This design prioritizes the robustness of the application and the user interface and prevents a single faulty listener from disrupting the entire system.
One way to detect and react to warnings that occur duing a listener callback is to clear the last warning at the top of the callback and query the last warning at the end of the callback or wherever the warning is most probable within the callback. If the lastwarning is not empty, you can rethrow the warning as an error.
Klont
Klont il 17 Feb 2024
Modificato: Klont il 17 Feb 2024
Thanks for your reply, Adam.
However, what you explain is the well known distinction between errors and warnings, i.e., stopping the flow of execution or just showing a message, respectively.
It doesn't explain why Mathworks decided to treat errors that happen in callbacks as warnings.
As coders, we have a simple way of converting an error in to a warning by catching it in a try/catch block. So we can decide if the "single faulty listener" should "disrupt the entire system" or not. This decision depends on what this fault is. It's not at all dependent on whether it happened in a callback or not.
Rethrowing warnings as errors is much more complicated. Especially when they happen in callbacks, because if i'd catch the lastwarn inside the callback function, I can't re-throw it as an error because someone decided that errors in callback are warnings.
This means that I'd have to use this lastwarn hack everywhere in the code that might trigger the callback. This could be dozens of places where I'd have to repeat the same boilerplate code.
To me, this seems inconsistent, inconvenient, unnecessary, and frankly, a blunder of design.
But perhaps I'm missing something?
I get where you're coming from, and I can see how this behavoir might feel like a head-scratcher. "Why" questions about long-established decisions can be tough to address. While I can't shed light on the historical 'why' behind this particular design choice, I could offer suggestions.
> we can decide if the "single faulty listener" should "disrupt the entire system" or not
I'm not sure that I follow this argument without a clarifying use case example. Listener callbacks have their own workspace so even if a listener callback would throw an error it wouldn't affect or disrupt any processes outside of that workspace. When there is an error within a listener callback, execution stops at that line which is a disruption to the processes within that workspace.
Try/catch statements still function within listener callbacks, although they can't be used to rethrow an error. They are still an effective way to detect and react to errors within the listener callback.
Here's an example.
I've created a faulty listener that updates the color of a marker any time the axes limit change. However, the marker no longer exists which causes an invalid or deleted object error in the listener callback.
I've caught the error and displayed the error message as red text along with a beep to simulate a MATLAB error.
Run this from a script and then manually drag the axes. Make sure your speakers are on.
figure
ax = axes;
h = plot(.5,.5,'+','MarkerSize',40,'LineWidth',5);
addlistener(ax, {'XLim', 'YLim'}, 'PostSet', @(~,~)listenerFcn(h));
delete(h)
function listenerFcn(h)
% Responds to changes to axis limits
try
h.Color = rand(1,3);
catch ME
% Simulate error
beep
fprintf(2,[ME.message,newline])
end
end
You'll see a burst of successive beeps along with a stack of error messages.
Nathan Blanc
Nathan Blanc il 18 Feb 2024
Modificato: Nathan Blanc il 18 Feb 2024
Hi Adam, thanks for your patience in answering here. I have moved past this issue a while ago, but since the discussion was rekindeled, I can try and explain why this mechanism was so problematic for me, why the solution you offered is not ideal, and what I ended up doing. In a nutshell- because of this mechanism, I can't trust any of my "try/catch" commands to actually catch errors. However this can be solved by using a specific class aimed at catching errors and handling them.
Original Problem:
To simplify Things, let's say I have a class of objects called "blob.m" with a property "blobidy" that is restricted to be less than 10. A blob can "adopt" another blob, leading to a constant ratio of 2 between their blobidies. (meaning, the father always has twice the blobidy of the son) this is achieved by adding postset listeners to the blobidy property of both blobs. see attached file "blob.m".
My problem can be seen in "Original _Script.m". When I try to change the father's blobidy to 12 ,the error is caught, a dialogue box is displayed, an error counter is updated and the blobidies are restored to their original values. However when I try to change the son's blobidy to 6 (indirectly trying to change the father blobidy to 12 again), the error is not caught, the counter is not updated and the original values are not restored.
Adam's Suggestion:
Following Adam's suggestion, I can add a try-catch inside the post-set callback itself. see "blob_adam.m". However, this doesn't help me a lot as can be seen in "Adam_Suggestion.m". I can display the dialogue box, but I cannot update the error counter or restore the values, because the "Catch" occurs in a different workspace. I assume there are several workarounds for this, and here is the one I chose.
My workaround
My workaround, that worked pretty well even in the original, more complex problem, is this: I introduce a new class called "Global_Blob_King.m" that is in charge of the blob kingdom. Each blob knows its blob king (has a property "king"), and notifies it in case of an error. see "blob_workaround.m". The king is in charge of the error counter, and also in charge of saving and restoring the original values. as can be seen in "My_Workaround.m", this actually works.

Accedi per commentare.

Più risposte (1)

Jianfei
Jianfei il 30 Ago 2025
Modificato: Jianfei il 30 Ago 2025
You can use keyboard in testing and debugging phase. Just a workaround. It's annoying I need to remove them when releasing.
try
% Listener function code
catch ME
keyboard
end

Categorie

Scopri di più su Environment and Settings in Centro assistenza e File Exchange

Prodotti

Release

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by