89

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.

István Zachar
  • 47,032
  • 20
  • 143
  • 291
Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
  • 1
    Related stackoverflow link: http://stackoverflow.com/questions/7987162/how-to-tell-mathematica-to-quit-upon-a-debug-error – Murta Nov 30 '14 at 19:23

6 Answers6

84

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

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

Internal`AddHandler["Message", messageHandler]

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

It can be turned off using

Internal`RemoveHandler["Message", messageHandler]

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

Internal`HandlerBlock[
 {"Message", messageHandler},
 (* ... code here ... *)
]

The currently set message handlers can be retrieved using

Internal`Handlers["Message"]

(Internal`Handlers[] 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.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
  • 2
    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 '13 at 02:14
  • 3
    This functionality has made its way into a top-level function (sorta) with GeneralUtilities`WithMessageHandler which turns messages into Failure objects. – b3m2a1 Dec 12 '16 at 16:17
19

What about something like this?

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

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
Rojo
  • 42,601
  • 7
  • 96
  • 188
  • I just used ParallelEvaluate instead of DistributeDefinitions, and now it works fine in parallel too. I have some ideas why DistributeDefinitions doesn't work here, but the workaround is good enough for now. Please also see https://groups.google.com/d/msg/comp.soft-sys.math.mathematica/0hw5IkrdsTU/v2404uYo9GsJ – Szabolcs Feb 08 '12 at 18:53
  • Edited with ParallelEvaluate and as you said it works. Thanks for the link – Rojo Feb 08 '12 at 18:56
  • @Szabolcs, reading your question on your link, when you do x=1;ParallelEvaluate[x], it returns {1,1} because your main kernel evaluates the result {x,x} returned from the parallel kernels, not because x was automatically synched – Rojo Feb 08 '12 at 19:16
  • Thanks for pointing this out, you are right, ParallelEvaluate does not auto-sync (ParallelEvaluate@Hold@Evaluate[x] can be used for testing). But Parallelize does auto-distribute definitions, so my original problem that I asked about was valid :-) – Szabolcs Feb 08 '12 at 19:24
  • +1, good stuff! My version does not yet quite work for parallel, and your does. Nice! – Leonid Shifrin Feb 08 '12 at 19:37
  • Shouldn't there be a Protect at the end for completeness? And perhaps it's a good idea to add some code to restore the default situation? – Sjoerd C. de Vries Feb 09 '12 at 09:54
  • @SjoerdC.deVries yeah. It isn't even turned into a function yet, just a code cell. – Rojo Feb 09 '12 at 10:26
  • There are some more problems with this: 1. Check should not prevent aborting because a message is still printed when using Check alone (without Quiet). 2. The second argument of Quiet is not supported. suppose I could fix this by adding more code for specific situations, but it introduces a lot of complexity. Generally: the calculation should be aborted if a message would be printed. It should not be aborted if no message would be printed. – Szabolcs Feb 09 '12 at 13:19
  • @Szabolcs, let me know what you think of the edited version – Rojo Feb 09 '12 at 17:25
16

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[]] & ;
Internal`AddHandler["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.

Ralph Dratman
  • 1,250
  • 12
  • 20
13

I've written a function CheckReturn that attempts to behave just like Check, except that it returns immediately if a message is generated. Also, if Quiet wrappers are used external or internal to CheckReturn, the behavior is consistent with how Check works. The code is given at the end. Here are some examples:

CheckReturn[1/0; Print[2], $Failed]
Check[1/0; Print[2], $Failed]

Power::infy: Infinite expression 1/0 encountered.

$Failed

Power::infy: Infinite expression 1/0 encountered.

2

$Failed

Notice that using CheckReturn, 2 was not printed. So far so good. Now, let's use an external Quiet:

Quiet @ CheckReturn[1/0; Print[2], $Failed]
Quiet @ Check[1/0; Print[2], $Failed]

$Failed

2

$Failed

In both cases the message is detected and failure expression is returned, but CheckReturn returns immediately without printing 2. Similarly, if we use an internal Quiet:

CheckReturn[ Quiet[1/0]; Print[2], $Failed]
Check[ Quiet[1/0]; Print[2], $Failed]

2

2

In both cases the internal Quiet is respected, and the message is not detected. CheckReturn has the option "CheckQuietedMessages"->False. If we set this option to True, than the internal Quiet is disregarded:

CheckReturn[ Quiet[1/0]; Print[2], $Failed, "CheckQuietedMessages"->True ]

Power::infy: Infinite expression 1/0 encountered.

$Failed

Just like Check has a 3-arg version where explicit messages can be specified, the same is possible with CheckReturn:

CheckReturn[ 1/0; Print[2], $Failed, Power::infy ]

Power::infy: Infinite expression 1/0 encountered.

$Failed

Finally, if messages are turned off, than CheckReturn ignores them as well:

Off[Power::infy]
CheckReturn[ 1/0; Print[2], $Failed, Power::infy]
Check[1/0; Print[2], $Failed, Power::infy]

2

2

Note that I didn't consider parallel behavior. Here is the code:

SetAttributes[CheckReturn,HoldAll]
Options[CheckReturn]={"CheckQuietedMessages"->False};

CheckReturn[body_,return_, OptionsPattern[]] := Module[{handler,flag},
    With[{stack = If[TrueQ@OptionValue["CheckQuietedMessages"], _, quietStack[]]},
        handler[Hold[mess_Message, True]]:=Throw[$Failed,flag];
        handler[Hold[mess:Message[mn_,___], False]] /; quietedMessageCheck[HoldForm[mn],stack] := Throw[
            Hold[mess],
            flag
        ]
    ];

    Catch[
        Internal`HandlerBlock[{"Message",handler},body],
        flag,
        (ReleaseHold[#];return)&
    ]
]

CheckReturn[body_, return_, m_, OptionsPattern[]]:=Module[{pred,handler, flag},
    pred = messagePredicate[m];
    (
    With[{stack = If[TrueQ@OptionValue["CheckQuietedMessages"], _, quietStack[]]},
        handler[Hold[mess:Message[mn_?pred,___], True]] := Throw[$Failed,flag];
        handler[Hold[mess:Message[mn_?pred,___], False]] /; quietedMessageCheck[HoldForm[mn],stack] := Throw[
            Hold[mess],
            flag
        ]
    ];

    Catch[
        Internal`HandlerBlock[{"Message", handler}, body],
        flag,
        (ReleaseHold[#];return)&
    ]
    ) /; pred=!=$Failed
]

SetAttributes[{messagePredicate, messageRules}, HoldAll]
messagePredicate[m_] := Replace[
    messageRules[m],
    r:Except[$Failed] :> Function[Null,ReplaceAll[HoldForm[#], r], HoldAll]
]

messageRules[MessageName[General, m_]] := HoldForm[MessageName[_,m]] -> True
messageRules[MessageName[t_, m_]] := HoldForm[MessageName[t,m]] -> True

messageRules[m:{__MessageName}] := messageRules /@ Unevaluated[m]

messageRules[m_String] := Replace[
Hold[m] /. $MessageGroups,
  {
  Hold[mn:{__MessageName}] :> messageRules[mn],
  _ :> (Message[CheckReturn::mgre, m]; $Failed)
    }
]

messageRules[m_] := (Message[Message::name, HoldForm[m]]; $Failed)

quietStack[] := Alternatives @@ (Stack/.Internal`QuietStatus[])[[1,All,1]]

quietedMessageCheck[m_HoldForm, stack_] := Count[
    First[MessageList /. Internal`QuietStatus[]] /. m -> True,
    {True, stack}
] > 0
Carl Woll
  • 130,679
  • 6
  • 243
  • 355
9

The following works pretty well, at least in Mathematica 10:

  1. On the menu bar, go to Evaluation/Debugger Controls/Show Debugger Tools Window.
  2. On the window that pops up, check the box to "Break at Messages"

It will then stop and display a green box around the code that is outputting an error message.

Luke
  • 191
  • 1
  • 3
  • 1
    Actually I was aware of this when asking the question (see the very last paragraph), but I needed a way that doesn't require the front end. It turns out that the method used in the accepted solution is the same the debugger uses. It's good to point out this possibility explicitly though, so +1. – Szabolcs Oct 30 '14 at 18:01
  • Same option is directly in the Evaluation->Debugger popup in Mathematica 11.1 (checking or unchecking the described "Dhow Debugger Tools Windows" doesn't open a popup for me) – riddleculous Mar 30 '17 at 14:23
8

There were some attempts on that in this discussion. I also have this functionality in my debug function posted here

Leonid Shifrin
  • 114,335
  • 15
  • 329
  • 420
  • Which one do you recommend for practical use? It should work in an environment with no front end, and I need to generalize it for parallel evaluation. – Szabolcs Feb 08 '12 at 18:27
  • 1
    @Szabolcs I did not use ot for parallel, but I was debugging serious staff with debug, like stack traces with depth 30 or 50, digging deep into internal stuff, and it all worked quite well. So, I'd rather extend debug for parallel, because it serves me very well. It also is useful in that it gives you the (sort of a) stack trace. – Leonid Shifrin Feb 08 '12 at 18:30
  • @belisarius's idea works quite well, I'll take a detailed look at debug (for the future) after I've debugged this thing... – Szabolcs Feb 08 '12 at 18:34
  • Your debug function looks very useful. There's one big problem though: it breaks on Quieted messages as well. My code, as well as at least some package functions, uses Quiet at certain positions. – Szabolcs Feb 08 '12 at 18:41
  • @Szabolcs I will look into it – Leonid Shifrin Feb 08 '12 at 18:49
  • It was ultimately debug[] that saved me today. If/when you update it, could you consider copying it here? – Szabolcs Feb 08 '12 at 19:25
  • @Szabolcs I spent the last hour trying to get it work with parallel and Quiet. I am on the way, but not yet quite there, and probably have no more time to spend on it now. I will surely update it here once done, and put it high in my SE-related to-do list. Out of curiosity: how did you manage to use it if it does not work for parallel stuff? We could move this to chat if you wish. – Leonid Shifrin Feb 08 '12 at 19:35