# How to abort on any message generated?

Mathematica is a bit unusual as a programming language because it never stops on messages, regardless of whether the message is an error, a warning or just an informative message. It simply prints the message and continues with evaluation. This can cause an avalanche of messages and unpredictable behaviour (e.g. memory may get filled up, bringing the machine to a halt with swapping---this is what happened to me)

Is there a way to immediately abort when any message is generated?

Requirements:

1. if a message would be printed, always abort.
2. if no message would be printed, don't abort.
3. do print the first message so I have a hint about what went wrong
4. the mechanism should work with parallel computations and should abort the full evaluation (i.e. main kernel and all parallel kernels)

There are many ways to handle message printing, including On/Off, Quiet, and possibly others (such as setting some system options). The solution should work well with these. I am afraid manually handling all possible situations is too fragile (there's always a chance something got left out).

I found a solution on MathGroup which aborts, but does not print the message.

I suspect there must exist a robust and simple solution because the Debug palette has a "Break on messages" option.

-

The easiest and, so far, the best solution I have found is the following:

(* Put the following two lines at the top of every notebook. *)
messageHandler = If[Last[#], Interrupt[]] & ;
InternalAddHandler["Message", messageHandler];

The above code is slightly modified from Szabolcs's solution at the beginning of this thread. I changed Abort to Interrupt. The latter seems to work immediately, while it appears that Abort may be waiting for some portion of the evaluation to finish before stopping everything.

-
 Hi Ralph, thanks for the answer! I formatted your code for you. If you would like more information about how to do this yourself, have a look at this page. – Verbeia♦ Aug 9 '12 at 6:21 Thank you verbeia! As you correctly surmised, I could not figure out how to get the code to look right. – Ralph Dratman Aug 10 '12 at 11:46

I found a robust solution described in this MathGroup message by Maxim Rytin:

messageHandler = If[Last[#], Abort[]] &

This will abort the computation whenever a message would be printed.

It can be turned off using

InternalRemoveHandler["Message", messageHandler]

Alternatively this can be temporarily applied to a piece of code like this:

InternalHandlerBlock[
{"Message", messageHandler},
(* ... code here ... *)
]

The currently set message handlers can be retrieved using

InternalHandlers["Message"]

(InternalHandlers[] will return all existing handlers)

Whenever a message is generated, Hold[message, printed] is passed to all "Message" handler functions where message is the message text and printed is True is the message would be printed, False otherwise.

The debugging palette appears to use the same mechanism to break on messages.

To make it work with parallel evaluations, one can simply register the same handler on all kernels using ParallelEvaluate.

-
Caveat: functions such as Reduce, Refine and Solve can pass messages to handlers which have printed=True but are somehow never printed. These include FindMinimum::fmmp and N::meprec, which I'm guessing are harmless. – Tobias Hagge Mar 28 at 2:14

Function[i, {i, ParallelEvaluate[i]};, HoldFirst][
Unprotect[Message, Check, Quiet];
Module[{$guardMes = True,$guardChck = True, $guardQuiet = True}, Message[args___ /;$guardMes] := Block[{$guardMes = False}, Message[args]; If[Head[First@{args}] =!=$Off, Abort[]];
];
Quiet[args___ /; $guardQuiet] := Block[{$guardQuiet = False, $guardMes = False}, Quiet[args] ]; Check[args___ /;$guardChck] := Block[{$guardChck = False,$guardMes = False},
Check[args]
];
]
]

EDIT to try to reflect Szabolcs's and Sjoerd's concerns

Function[i, {i, ParallelEvaluate[i]};, HoldFirst][
Module[{$guardMes = True}, OnMessageAbort[] := ( Unprotect[Message]; Message[args___ /;$guardMes && Head[First@{args}] =!= $Off] := Block[{$guardMes = False, flag = False},
Internal`InheritedBlock[{$MessagePrePrint},$MessagePrePrint =
With[{fn = $MessagePrePrint}, Function[i, flag = True; fn[i], HoldAll]]; Message[args]; If[flag, Abort[];] ] ]; Protect[Message]); OffMessageAbort[] := ( Unprotect[Message]; Quiet[ Message[args___ /;$guardMes && Head[First@{args}] =!= \$Off] =.];
Protect[Message];
)
];
];
OnMessageAbort[ker_] := ParallelEvaluate[OnMessageAbort[], ker];
OnMessageAbort[All] := (ParallelEvaluate[OnMessageAbort[]];
OnMessageAbort[]);
OffMessageAbort[ker_] := ParallelEvaluate[OffMessageAbort[], ker];
OffMessageAbort[All] := (ParallelEvaluate[OffMessageAbort[]];
OffMessageAbort[]);

You run that once, and it defines (On/Off)MessageAbort[] in all kernels. You can call OnMessageAbort[] to turn it on on the kernel you run that, or OnMessageAbort[kernel] from the main kernel to turn it on on a particular kernel, just like the second argument to ParallelEvaluate. OnMessageAbort[All] turns it on in all of them. Same goes for OffMessageAbort

-