11

In the rotating package examples there is a command included before the document class.

\errorcontextlines32
\documentclass[twoside]{report}

When I apply \meaning\errorcontextlines to it, it does not show any definitions. What does it do?

yannisl
  • 117,160

2 Answers2

14

\errorcontextlines refers to the number of lines output by TeX upon finding an error, which should provide some context for the user in terms of the why the error occurred.

From the TeX Book (p 34):

If you use TeX format packages designed by others, your error messages may involve many inscrutable two-line levels of macro context. By setting \errorcontextlines=0 at the beginning of your file, you can reduce the amount of information that is reported; TeX will show only the top and bottom pairs of context lines together with up to \errorcontextlines additional two-line items. (If anything has thereby been omitted, you'll also see '...'.) Chances are good that you can spot the source of an error even when most of a large context has been suppressed; if not, you can say 'I\errorcontextlines=100\oops' and try again. (That will usually give you an undefined control sequence error and plenty of context.) Plain TeX sets \errorcontextlines=5.

In the above discussion it is assumed that \oops is undefined.

Werner
  • 603,163
  • 1
    Apparently, in LaTeX one can also use \setcounter{errorcontextlines}{100} instead of \errorcontextlines=100. (Though I don't see the point really.) – ShreevatsaR May 25 '17 at 15:44
  • @ShreevatsaR: Yes, those are different ways of setting counters. \X=Y is the TeX format, while \setcounter{X}{Y} is the LaTeX format. But, of course, since LaTeX is built on top of TeX, both syntaxes are valid in LaTeX. – Werner May 25 '17 at 15:45
  • @ShreevatsaR This is because \c@errorcontextlines is let equal to \errorcontextlines in LaTeX. – Ulrich Diez Dec 19 '21 at 02:34
1

This answer shows how to use \errorcontextlines / how to interpret the resulting context, and why the feature is useful & when the feature is not useful and what you can do.

See also: compiling - How to trace LaTeX errors efficiently? - TeX - LaTeX Stack Exchange


TeX has no call stack, but this is the closest in a macro expansion language.

How to use the feature

Consider this program (with appropriate preamble)

\errorcontextlines=10000
\def\c{1 \errorerror 2}
\def\b #1 {7 #1 8}
\def\a{5 \b {3 \c 4} 6}
7 \a 8

The relevant output is

! Undefined control sequence.
\c ->1 \errorerror 
                   2
<argument> 3 \c 
                4
\b #1 ->7 #1
             8
\a ->5 \b {3 \c 4} 
                   6
l.7 7 \a
         8

(Then TeX drops into a prompt (the line starts with ?).)

What the error message means:

  • The content of line 7 of some file (see this to find out which file it is) is 7 \a 8, and TeX has just read \a.(3)
  • \a expands to 5 \b {3 \c 4} 6.
  • \b expands to 7 #1 8.
  • #1 "expands" to 3 \c 4. (actually it's more like "#1 has the value of")
  • \c expands to 1 \errorerror 2.
  • After executing 7 {expands \a} 5 {expands \b {3 \c 4}} 7 3 {expands \c} 1 \errorerror(3), the error happens, and 2 4 8 6 8 is going to be executed next.

Usually, the bottom line will be the place in your code.

As usual with finding errors, most of the time the place you want to look for is the top-most layer that contains your code. (for example, if a and c is library/package function, and \b is your function, you would want to modify the definition of \b)

Limitations

Error while scanning arguments

In this case TeX will not report the line number correctly. See LaTeX debugging strategies and brace mismatching for more details.

Line number of macro is not shown

This can't be resolved (without recompiling TeX/modifying the execution somehow), TeX does not store where a macro is defined.

Line too short

To view the content of the ... at the start/end of lines, see this answer.

Missing intermediate context lines

The engine does explicit "tail call optimization" to avoid building up memory in a loop, therefore if some command (plus its arguments) is at the end of other command then it will be hidden from the context.

There's no way to disable this, except recompiling TeX. (compared to C where compilers can do tail recursion, but do not do that in debug mode)

As an example, if the code is modified to

\errorcontextlines=10000
\def\c{1 \errorerror}
\def\b#1{7 #1}
\def\a{5 \b{3 \c}}

7 \a 8 \def\a#1{1 #1} \a{3 4 \errorerror 5 6}

the error message will be simply

\c ->1 \errorerror

l.13 7 \a 8

All the intermediate error context lines are missing.

Nevertheless, in this case you know that the cause is tail call optimization, without recompiling TeX you may be able to look at the definition of the macros (either \show or latexdef) to figure out the missing ones (it's always the last one. For the context line types other than "macro" it's a bit harder, but for <argument> type there's \tracingmacros).

An example where this behavior makes the problem very hard to debug: see question.

Missing bottom context lines

There's yet another case that you can't get the topmost layer of your code: \usepackage.

See the linked comment in why is this error message line number wrong? - TeX - LaTeX Stack Exchange.

For a workaround, see the comment below that.

Wrong token list?

(3): Actually, \a (the last token in the first line) is the last that TeX has "read", not necessarily the thing that is currently being expanded.

Besides, if the context is from a file, TeX will show the line content, not the actual pending next tokens. And if the context is from a macro, TeX will show the macro definition (even though TeX has the capability to "reconstruct" code from parsed token list)

Some operations may make TeX read some more commands, that the one that contains the error definition is not the one at the last of the first line.

For example:

\def\a{1 \errorerror 2}

7 \expandafter \a \a 8

Error message:

\a ->1 \errorerror
                   2
\a ->
     1 \errorerror 2
l.12 7 \expandafter \a \a
                        8

Note that:

  • The error is caused by the expansion of the first \a macro, not the second,
  • The second \a appears in its unexpanded form instead of once-expanded form.

Missing arrow (->) / arguments

A relatively trivial one, but note that if the macro body is too long the arrow -> might be omitted.

./a.tex:11: Undefined control sequence.
\aaaaaaaaaaaaaaaaaaaa ...lax \relax \relax \ERROR 
                                                  \relax \relax \relax \rela...

l.11 \aaaaaaaaaaaaaaaaaaaa

In this case it should still be understood that the macro name is \aaaaaaaaaaaaaaaaaaaa, and it might have some argument etc. See the code below.

\documentclass{article}
\errorcontextlines=100
\def\aaaaaaaaaaaaaaaaaaaa #1#2#3{
\relax \relax \relax \relax \relax \relax \relax \relax \relax \relax
\ERROR
\relax \relax \relax \relax \relax \relax \relax \relax \relax \relax
}
\aaaaaaaaaaaaaaaaaaaa {} {} {}

Missing \

This can happen too. The code

\escapechar=-1
\def\aaaaaaaaaaaaaaaaaaaa #1#2#3{
\relax \relax \relax \relax \relax \relax \relax \relax \relax \relax
\ERROR
\relax \relax \relax \relax \relax \relax \relax \relax \relax \relax
}
\aaaaaaaaaaaaaaaaaaaa {} {} {}

creates the message similar to above, but without the \s.

./a.tex:12: Undefined control sequence.
aaaaaaaaaaaaaaaaaaaa ...x relax relax relax ERROR 
                                                  relax relax relax relax re...

l.12 \aaaaaaaaaaaaaaaaaaaa {} {} {}

Wrong macro name where a token list comes from

This can sometimes happen in a "callback" in expl3 code or similar.

For example

\cs_new_protected:Npn \mymacro {
    \peek_analysis_map_inline:n {ab \error cd}
}
\mymacro 1

then the traceback will have the form

\__tl_analysis_map_1:nnN #1#2#3->\group_end: ab\error 
                                                      cd\__tl_peek_analysis_loop:NNn \prg_break_point:Nn \peek_analysis_map_break: {}
l.9 \mymacro 1

instead of what you might expect, that is

\mymacro->\peek_analysis_map_inline:n {ab \error
                                                 cd}
l.9 \mymacro 1

although the erroneous token \error originally comes from \mymacro, the traceback shows it is from \__tl_analysis_map_1:nnN instead
(because internally the argument {\peek_analysis_map_inline:n {ab \error cd}} is stored into that macro, then executed from there).

Similar situation happens with simple conditional such as

\cs_new_protected:Npn \mymacro {
    \bool_if:NT \c_true_bool {
        ab \error cd
    }
}
\mymacro

which gives the traceback

<argument> ab\error 
         cd
\use:n #1->#1

l.11 \mymacro

Wrong indentation

For some reason, if the first example is compiled with LuaLaTeX instead of PDFLaTeX, the indentation of the line below <argument> will be wrong:

! Undefined control sequence.
\c ->1 \errorerror 
                   2
<argument> 3 \c 
     4
\b #1 ->7 #1
             8
\a ->5 \b {3 \c 4} 
                   6
l.7 7 \a
       8

This problem is fortunately not very serious and it's still possible to tell which line is which.

CR/LF characters in the output

Normally there would be 2 lines, but sometimes there might be more because the token list itself contain some CR/LF character.

I don't know any workaround for this one.

Side note

user202729
  • 7,143
  • E.g., with your first example \errorcontextlines=10000|\def\c{1 \errorerror 2}|\def\b{3 \c 4}|\def\a{5 \b 6}|7 \a 8 the relevant output on my system does not contain any # , so probably the example was modified after providing the description of the output. – Ulrich Diez Apr 10 '22 at 14:35