Short Version
The ultimate cause of this problem is an evaluation leak that occurs when an expression of the form MakeBoxes[StringForm[...]]
is evaluated.
Longer Version
MakeBoxes
has the attribute HoldAllComplete
. This allows it to create the box representation of any expression without evaluating it. For example:
MakeBoxes[1 + 1]
(* RowBox[{"1", "+", "1"}] *)
MakeBoxes[Print[1]]
(* RowBox[{"Print", "[", "1", "]"}] *)
Apparently, StringForm
gets special treatment by MakeBoxes
:
MakeBoxes[StringForm["Hello, ``", "World"]]
(*
InterpretationBox["\"Hello, World\"",
StringForm["Hello, ``","World"], Editable -> False]]
*)
Notice how the StringForm[...]
expression has been evaluated to produce the label for the InterpretationBox
, in addition to the unevaluated expression that serves as the content of that box.
This is all well and good when the StringForm
expression stands alone, but what about when it is an expression awaiting the values of local variables, like this:
MakeBoxes[StringForm[x, y]]
(*
During evaluation of In[20]:= StringForm::string: String expected at position 1
in StringForm[x,y]. >>
RowBox[{StringForm,[,RowBox[{x,,,y}],]}]
*)
Here we see a message very much like the one exhibited in the question. A simple RowBox
is still generated, despite the message.
Isn't it invalid to have a free-standing StringForm
expression like that? Yes, but we must remember that MakeBoxes
is invoked recursively on all of its subexpressions. So we get an unexpected message when we try to generate boxes for a perfectly valid definition like this:
MakeBoxes[zot[x_, y_] := StringForm[x, y]]
(*
During evaluation of In[26]:= StringForm::string: String expected at position 1
in StringForm[x,y]. >>
RowBox[{RowBox[{"zot", "[", RowBox[{"x_", ",", "y_"}], "]"}], ":=",
RowBox[{"StringForm", "[", RowBox[{"x", ",", "y"}], "]"}]}]
*)
The StringForm
did not start out to be an invalid free-standing expression, but the recursive action of MakeBoxes
made it so.
More Gory Details
How do we know that StringForm
is to blame?
If we evaluate the expressions from the question with the debugger turned on and message breaks enabled, we see this stack trace:

We can see that StringForm
triggered the first error, and we can see all of the behaviour described above in the preceding stack frames.
Why does the error only occur the first time the expression is evaluated?
The first time that the expression is evaluated, a great many packages are auto-loaded. Normally, this loading process is not shown by Trace
. But because the example in the question uses TraceInternal
, all of these internal activities are shown in the trace.
The first message is generated when MakeBoxes
is called upon an auto-loaded definition that looks like this (in outline):
Parallel`Debug`Private`tracePrint[...] /; MemberQ[...] :=
CheckAbort[
Print[..., StringForm[Parallel`Debug`Private`sf, Parallel`Debug`Private`args]]
, Abort[]
]
In subsequent evaluations, these auto-loads do not occur so neither does the problem. Also, if we turn off TraceInternal
, then the problem does not occur on even the first evaluation since none of the auto-load expressions appear in the trace.
Are all the messages due to this one problem?
No. Some of the messages are knock-on effects of this first message. Others are due to further occurrences of StringForm
. And yet others appear to be due to similar evaluation leaks in other components.
Why does the problem only appear when there are four variables instead of three?
I'm not sure, but I have a guess. Observe the size of the trace output for each of the following variable counts:
1 variable: 2.9 meg
2 variables: 65 meg (error occurs)
3 variables: 1.5 meg
4 variables: 64 meg (error occurs)
5 variables: 7.0 meg
6 variables: 7.5 meg
12 variables: 10.6 meg
Note correlation of error occurrence with the spike in the output size for quadratic and quartic equations. I speculate that Simplify
uses much more elaborate techniques for equations of this kind. Perhaps part of that elaboration involves loading special libraries... and at least one of those extra libraries ends up loading the troublesome Parallel`Debug
definition. Or it may be simply that the enormous size of the trace output crosses a magic array size threshold, triggering the parallel computation machinery.
Trace
behavior you described. Very strange. $\endgroup$ – bbgodfrey Feb 28 '15 at 1:01