Function Repository Resource:

MessageFailure

Source Notebook

Print a message and return a failure object

Contributed by: Richard Hennigan (Wolfram Research)

ResourceFunction["MessageFailure"]["message"]

prints "message" as a Message and returns a corresponding Failure object.

ResourceFunction["MessageFailure"]["tag","message"]

uses "tag" as the Failure tag.

ResourceFunction["MessageFailure"]["tag",<||>]

determines the message text and failure details from the given Association.

ResourceFunction["MessageFailure"][symbol::tag]

prints the message symbol::tag and returns a corresponding Failure object.

ResourceFunction["MessageFailure"][symbol::tag,e1,e2]

prints a message and returns a Failure, inserting the values of the ei as needed.

Details and Options

ResourceFunction["MessageFailure"][] gives a predefined generic error message.
ResourceFunction["MessageFailure"]["tag",Automatic] gives a generic message based on the given "tag".
The association assoc in ResourceFunction["MessageFailure"]["tag",assoc] typically includes:
"MessageTemplate"a string template for a message
"MessageParameters"parameters to use for the message template
The parameters are effectively inserted into the message template using TemplateApply.
Message templates can use either positional (`n`) or named (`namei`) arguments.

Examples

Basic Examples (6) 

Print a generic error message and return a Failure object:

In[1]:=
ResourceFunction["MessageFailure"][]
Out[1]=

Specify the message text:

In[2]:=
ResourceFunction["MessageFailure"]["This is an error message."]
Out[2]=

Specify a tag:

In[3]:=
ResourceFunction[
 "MessageFailure"]["MyTag", "This is an error message."]
Out[3]=

Choose a generic message based on the given tag:

In[4]:=
ResourceFunction["MessageFailure"]["MyTag", Automatic]
Out[4]=

Use Message syntax:

In[5]:=
ResourceFunction["MessageFailure"][f::argx, f, 2]
Out[5]=
In[6]:=
ResourceFunction["MessageFailure"][Power::infy, HoldForm[1/0]]
Out[6]=

Use Failure syntax:

In[7]:=
ResourceFunction[
 "MessageFailure"]["InvalidRange", <|
  "MessageTemplate" -> "Enter a number lower than `Number`", "MessageParameters" -> <|"Number" -> 10|>|>]
Out[7]=
In[8]:=
ResourceFunction[
 "MessageFailure"]["InvalidInput", <|
  "Message" -> "Input must be a string"|>]
Out[8]=

Scope (2) 

Include additional metadata:

In[9]:=
ResourceFunction["MessageFailure"]["RestrictionFailure",
 <|"MessageTemplate" :> Interpreter::numberinterval,
  "MessageParameters" -> <|"Min" -> 1, "Max" -> 10, "Input" -> {"100"}|>,
  "Interval" -> Interval[{1, 10}],
  "Input" -> {"100"},
  "Type" -> "Number"|>
 ]
Out[9]=

Specify a different message symbol:

In[10]:=
ResourceFunction["MessageFailure"]["RestrictionFailure",
 <|"MessageTemplate" :> Interpreter::numberinterval,
  "MessageParameters" -> <|"Min" -> 1, "Max" -> 10, "Input" -> {"100"}|>,
  "MessageSymbol" -> MyFunction|>
 ]
Out[10]=

Options (8) 

MessageFunction (3) 

Use a custom message function:

In[11]:=
ResourceFunction["MessageFailure"][Power::infy, HoldForm[1/0], "MessageFunction" -> Print@*List]
Out[11]=

Issue the message with ResourceFunctionMessage instead of Message:

In[12]:=
ResourceFunction["MessageFailure"][Power::infy, HoldForm[1/0], "MessageFunction" -> ResourceFunction["ResourceFunctionMessage"]]
Out[12]=

Define a function that uses the default setting "MessageFunction"Automatic:

In[13]:=
AddOne // ClearAll;
AddOne::integer = "`1` is expected to be an integer.";
AddOne[x_Integer] := x + 1;
AddOne[other_] := ResourceFunction["MessageFailure"][AddOne::integer, other];

By default, Message will be used:

In[14]:=
AddOne /@ {5, "string", 8}
Out[14]=

Once converted to a resource function, ResourceFunctionMessage will be automatically used instead:

In[15]:=
rfAddOne = DefineResourceFunction[AddOne]
Out[15]=
In[16]:=
rfAddOne /@ {5, "string", 8}
Out[16]=

Use SetOptions to change this globally:

In[17]:=
SetOptions[ResourceFunction["MessageFailure"], "MessageFunction" -> Message]
Out[17]=
In[18]:=
rfAddOne /@ {5, "string", 8}
Out[18]=

Restore the default setting:

In[19]:=
SetOptions[ResourceFunction["MessageFailure"], "MessageFunction" -> Automatic];

Verbose (2) 

By default, only a small number of keys are included in the Failure object:

In[20]:=
simple = ResourceFunction["MessageFailure"][Power::infy, HoldForm[1/0]]
Out[20]=
In[21]:=
simple[[2]]
Out[21]=

Use "Verbose"True to include additional metadata used internally by MessageFailure:

In[22]:=
verbose = ResourceFunction["MessageFailure"][Power::infy, HoldForm[1/0], "Verbose" -> True]
Out[22]=
In[23]:=
verbose[[2]]
Out[23]=

Stack (3) 

Include a stack trace in the failure metadata:

In[24]:=
rsqrt[x_] := If[TrueQ[x >= 0], Sqrt[x], ResourceFunction["MessageFailure"][rsqrt::nnarg, x, "Stack" -> True]];
rsqrt::nnarg = "The argument `1` is not greater than or equal to zero.";
In[25]:=
f[g[1, fail = rsqrt[-2.25]; 2]]; fail
Out[25]=

View the stack trace:

In[26]:=
fail["Stack"] // Column
Out[26]=

Include a more detailed stack trace in the failure metadata:

In[27]:=
rsqrt[x_] := If[TrueQ[x >= 0], Sqrt[x], ResourceFunction["MessageFailure"][rsqrt::nnarg, x, "Stack" -> Full]];
rsqrt::nnarg = "The argument `1` is not greater than or equal to zero.";
In[28]:=
f[g[1, fail = rsqrt[-2.25]; 2]]; fail
Out[28]=

View the stack trace:

In[29]:=
fail["Stack"] // Column
Out[29]=

Use StackComplete for even more detail:

In[30]:=
StackComplete[f[g[1, fail = rsqrt[-2.25]; 2]]; fail]
Out[30]=
In[31]:=
fail["Stack"] // Column
Out[31]=

When using the option setting "Verbose"True, the stack will also include evaluations made by MessageFailure as well:

In[32]:=
rsqrt[x_] := If[TrueQ[x >= 0], Sqrt[x], ResourceFunction["MessageFailure"][rsqrt::nnarg, x, "Stack" -> Full, "Verbose" -> True]];
rsqrt::nnarg = "The argument `1` is not greater than or equal to zero.";
In[33]:=
f[g[1, fail = rsqrt[-2.25]; 2]]; fail
Out[33]=

The stack trace now includes internal evaluations of MessageFailure as well:

In[34]:=
fail["Stack"] // Map[Short] // Column
Out[34]=

Applications (4) 

Create directives for defining new functions:

In[35]:=
BeginDefinition // ClearAll;
BeginDefinition // Attributes = {HoldFirst};
BeginDefinition[s_Symbol] := (Unprotect[s]; ClearAll[s]);
In[36]:=
EndDefinition // ClearAll;
EndDefinition // Attributes = {HoldFirst};
EndDefinition[s_Symbol] := (
   expr : s[___] := ResourceFunction["MessageFailure"][
     s, <|"MessageTemplate" -> "No definition found for `1`.", "MessageParameters" -> {HoldForm@expr}|>];
   Protect@s
   );

Define a new function using these directives:

In[37]:=
MyFunction // BeginDefinition;
MyFunction[x_Integer] := x + 1;
MyFunction[x_Integer, y_Integer] := x + y;
MyFunction // EndDefinition;

Test the function:

In[38]:=
MyFunction[5]
Out[38]=
In[39]:=
MyFunction[5, 6]
Out[39]=

Undefined inputs are automatically caught as an error:

In[40]:=
MyFunction[a, b, c]
Out[40]=

Properties and Relations (6) 

The message can be retrieved from the Failure object:

In[41]:=
failure = ResourceFunction["MessageFailure"][Power::infy, HoldForm[1/0]]
Out[41]=
In[42]:=
failure["Message"]
Out[42]=

A message can be reissued from the Failure object using Message:

In[43]:=
func::number = "Argument `1` should be a number";
In[44]:=
failure = ResourceFunction["MessageFailure"][func::number, abc]
Out[44]=
In[45]:=
Message[Evaluate[failure]]

MessageFailure can also reissue the message from the Failure:

In[46]:=
ResourceFunction["MessageFailure"][failure]
Out[46]=

MessageFailure can use modern template specifications:

In[47]:=
MyFunction::datedmsg = "<*DateString[]*>: `ErrorMessage`";
In[48]:=
ResourceFunction["MessageFailure"][
 MyFunction::datedmsg, <|"ErrorMessage" -> "Something broke!"|>]
Out[48]=

Compare to Message:

In[49]:=
Message[MyFunction::datedmsg, <|"ErrorMessage" -> "Something broke!"|>]

Message templates need not be strings:

In[50]:=
ResourceFunction["MessageFailure"]["MyTag",
  <|"MessageTemplate" :> Graphics[{Circle[], Inset[TemplateSlot["ErrorMessage"], {0, 0}]}],
    "MessageParameters" -> <|
     "ErrorMessage" -> "Something broke!"|>|>];

MessageFailure can print messages for Failure objects that use named template parameters:

In[51]:=
failure = Failure["InvalidRange", <| "MessageTemplate" -> "Enter a number lower than `Number`",
   "MessageParameters" -> <|"Number" -> 10|>
   |>]
Out[51]=
In[52]:=
ResourceFunction["MessageFailure"][failure]
Out[52]=

Compare to Message:

In[53]:=
Message[Evaluate[failure]]
Out[53]=

Messages with named template slots are temporarily redefined to avoid giving unsupported templates to Message:

In[54]:=
MySymbol // ClearAll;
MySymbol::testing = "The parameter appears here: `NamedParameter`";
In[55]:=
ResourceFunction["MessageFailure"][
 MySymbol::testing, <|"NamedParameter" -> 123|>]
Out[55]=

Use a message handler to print the current message definition at the time of message generation:

In[56]:=
Internal`HandlerBlock[{"Message", If[#[[2]], Extract[#, {1, 1}, EchoEvaluation]] &},
 ResourceFunction["MessageFailure"][
  MySymbol::testing, <|"NamedParameter" -> 123|>]
 ]
MySymbol::testing"The parameter appears here: \!\(\*RowBox[{\"123\"}]\)"MySymbol::testing
Out[56]=

The original message definition is restored:

In[57]:=
MyFunction::testing
Out[57]=

Possible Issues (2) 

Using named template slots or template expressions in message definitions gives a template that is not supported by Message:

In[58]:=
MyFunction::datedmsg = "<*DateString[]*>: `ErrorMessage`";
In[59]:=
Message[MyFunction::datedmsg, <|"ErrorMessage" -> "Something broke!"|>]

Use MessageFailure to issue these kinds of messages instead:

In[60]:=
ResourceFunction["MessageFailure"][
 MyFunction::datedmsg, <|"ErrorMessage" -> "Something broke!"|>]
Out[60]=

Non-string templates won't appear formatted in the resulting Failure object:

In[61]:=
failure = ResourceFunction["MessageFailure"][
  "AThingBroke",
  <|
   "MessageTemplate" :> Row[{DateString[], " ", TemplateSlot["ErrorMessage"]}],
   "MessageParameters" -> <|
     "ErrorMessage" -> "Something broke."|>
   |>
  ]
Out[61]=

The printed message cannot be retrieved from the failure either:

In[62]:=
failure["Message"]
Out[62]=

Version History

  • 1.0.0 – 09 August 2021

Related Resources

License Information