33

What is the recommended way to track down brace mismatches in LaTeX? I have a large beamer presentation, but this equally applies to any other LaTeX work I've done.

In other computer languages I've used pretty printers to highlight where things mismatch, but I can't seem to find a pretty printer for the LaTeX code itself rather than some other language inside in LaTeX.

My next thought is to start commenting out large sections of the source until the problem is pinned down.

What other strategies might be used?

8
  • 9
    Some editors do delimiter highlighting. Then it's quite easy to find orphaned braces.
    – Count Zero
    Sep 13, 2012 at 14:39
  • 12
    I tell my students to compile early and often - any program in any language, including TeX. Then you know the error is in the small piece you just modified. I always regret it when I don't take my own advice. Sep 13, 2012 at 14:39
  • 1
    @CountZero Agreed unles it's a big file that you've been editing in a gui and the mouse decides to move without your input... you hit space and you've accidentally deleted a brace and the screen jumps - yes I know it's not ideal... but hey I blame the driver! Oh dear!
    – Sean
    Sep 13, 2012 at 14:45
  • 3
    The log file gives a line number that may help. Another strategy is to move \end{document} earlier in the file to see when the error disappears. Try using this in a binary search strategy. Sep 13, 2012 at 15:52
  • 2
    As always: use emacs (and AUCTeX). Simple problems are easily found through syntax highlighting or M-x check-parens. For more complex needs there's things like rainbow-delimiters.el.
    – jon
    Sep 13, 2012 at 20:21

7 Answers 7

22

The log file usually gives some help. For example if you start an environment without ending it then you get

! LaTeX Error: \begin{quote} on input line 16 ended by \end{document}.

which tells you where group started, if it doesn't tell you where it should have finished.

If you have mis-matched { } pairs it depends whether they are being used for grouping or argument delimiting.

In the former case you get

(\end occurred inside a group at level 1)

which tells you something is bad and if at the start of the document you put

\tracinggroups=1

you get in addition

### simple group (level 1) entered at line 16 ({)
### bottom level

which tells you where the { was.

If it is argument matching ie you have \textbf{ with no } then you get:

Runaway argument?
{ \par aa bb xx cc \par \par \par \par 4 $\hat {\hat {\mathcal {A}}} \ETC.
! File ended while scanning use of \textbf .

which gives you some context, but not a line number, although if you have the tracinggroups set as above it is easy to guess as you are told the last group that was entered or left before the error, in this case the log shows

{leaving math shift group (level 1) entered at line 14}
)
Runaway argument?

so it isn't too hard to spot the error on line 16 as line 14 was OK and line 15 (in this case) was empty.

3
  • Well, many LaTeX2e commands are defined in terms of @-ful macros which actually grab the argument. That means that the error messages are not nearly as helpful as you make them seem. Joseph's worked hard to get better error messages in xparse (the function grabbing the 3rd argument of an xparse-defined command \foo is named \foo (arg 3)). Sep 13, 2012 at 16:52
  • @BrunoLeFloch well yes the command names shown can be fairly arbitrary depending on the expansion path but you can usually figure out the line number which was what I wanted to highlight. Sep 13, 2012 at 19:06
  • @BrunoLeFloch Actually, it's mainly '\foo ' (with a space in), although some of the expandable ones are a bit different. Principal is correct though: give an error that makes some sense to the user :-)
    – Joseph Wright
    Sep 13, 2012 at 20:21
11

the answers so far address problems in a single-file job. things get a bit more complicated if there are multiple files processed with \include or \input. when that happens, and there is a report that (\end occurred inside a group at level 1), if a line number is given, you don't know what file that line is in.

i use emacs, and take advantage of the fact that one can ask how-many for a file. first, get a list of the files being included. then, go into them one by one. ask how many { and then how-many }. if the counts don't match, you've potentially found the problem file. if you're lucky, your warning included a line number, so use it. if not, go halfway down the file, and (preferably at a "clean" location like a paragraph or section break) repeat the how-many mantra. this is usually enough to localize the problem well enough to inspect the text by eye.

another thing to check is matching counts of \begin{ and \end{ -- the open brace is important, since some users define their own \beginxxx commands, and you probably don't want to check those, at least in the first cut.

alternatively, use the approach of inserting \end{document} at various points in the problem file until the warning goes away, then eyeball the intervening text for the problem. (\endinput also works, although it's a primitive, not a latex command. this is actually more useful than \end{document} when searching an \included or \input file, as it affects only that particular file.)

yet another approach is to comment out \include and \input statements, starting with the last one; when the warning disappears, you've found the problem file, and can then use one of the other tactics inside that file.

(i used the 'how-many` approach on a 15-chapter book a few days ago, and found the problem in less than 10 minutes; it was in chapter 3, so i was lucky.)

4
  • +1 for how-many. Another thing in an unending list of things emacs does that I didn't know about. But regarding the issue of \included or \inputted files, I thought that's what the -file-line-error option was supposed to help with..?
    – jon
    Sep 20, 2012 at 1:50
  • @jon -- well, i didn't know about the file-line-error option, so it seems i have some studying up to do too. thanks. Sep 21, 2012 at 19:43
  • 1
    Vim version of the Emacs how-many WORD is :s/WORD//n. The Vim plugins matchit or Automatic TeX Plugin will highlight matching \begin{} and \end{} statements.
    – Sameer
    Feb 14, 2015 at 0:20
  • added some more information on matching and cutting files short. (spent about five hours yesterday doing just that, trying to diagnose a hard loop. finally narrowed the problem down to a single sentence, though the exact cause hasn't been determined yet; that goes into a small dedicated test file.) Feb 3, 2017 at 13:54
5

I had similar problem and wanted to go through all pairs, but I got lost in the middle.

l.129 \input{chap_models/main.
I suspect you have forgotten a }', causing me..

so I wrote small script in python: https://github.com/sacherus/latex_tools/blob/master/para_parser.py

main_simple.tex:

\begin{document}
Lorem ipsum.
Don't bother %{}}
Don't bother2 \{
\enddocument}

run: $ ./para_parser.py -i main_simple.tex

output: Input file is main_simple.tex Found redundant parenthesis in ('}', 5)

So there is redundant parenthesis in line 5.

0
4

LEd (http://www.latexeditor.org/) colours braces so that you can immediately see which ones match:

enter image description here

I find that detecting problems using this is much faster than e.g. using an editor that highlights the brace matching the one under the cursor.

Edit: turns out this is called 'rainbow parens'; cf. e.g.

http://www.emacswiki.org/emacs/RainbowDelimiters http://www.vim.org/scripts/script.php?script_id=3772

3
  • 1
    I have found LEd to be really unstable. Without any continuing development (current download is a beta dated 2009), I found that it was prone to crashing on Win7, and it would often lose lots of work, or files became corrupted.
    – J M
    Sep 13, 2012 at 16:38
  • @Mohan Looks like it's Windows only and I'm on Linux (oops should have said!)
    – Sean
    Sep 13, 2012 at 16:49
  • 1
    The feature is definitely supported by other editors (see my edit). . I wish I could figure out what program this was taken from... s3.amazonaws.com/imgly_production/3303667/large.png
    – Mohan
    Sep 13, 2012 at 18:59
4

I think the best weapon is a good text editor, and a little knowledge on your part on how to use it. TextMate, for instance, has tab triggers. So I can type begin + Tab, and it automatically creates begin and end, and allows me to type out the environment. That already takes care of a lot, lot of errors. Similarly with bracket mismatches, in many situations good text editors will change the syntax highlighting depending on what type of TeX code you are working on. I use most brackets in formulas, so if I forget to close a curly bracket, TextMate indicates that by “miscoloring” subsequent code.

The second thing is good code formatting: don't write code willy nilly, use indents and % as additional visual aids to your advantage. I lead and trail all environments with %, for example, that makes it much easier to locate that in my code.

Thirdly, define a sensible amount of your own commands. E. g. if you always type \mathcal{H} to indicate a Hilbert space, \Hil is not only faster, but you avoid the issue of curly braces altogether.

2
  • Good, useful answer. Although, I would note the sensible amount of own commands should be minimal. In TeX use define and in LaTeX you should use newcommand. Also, suggest you would always define the commands in the file where they are used, so that if you send the code to someone else it will compile. And finally welcome to TeX.SE and I trust you will continue to participate. Jun 9, 2016 at 1:10
  • Thanks for the welcome, and yes, I intend to. I have amassed a number of standard definitions, \e. g. \R, \C for the fields of real and complex numbers, \scpro{}{} for a scalar product and \abs{} for the absolute value. I have also included variations on the sizes (I prefer to choose delimiter sizes manually), so there is \sabs{}, \babs{} and \Babs{} for small absolute value, \big absolute value and \Big absolute value.
    – Max Lein
    Jun 9, 2016 at 4:22
3

I like going through the output, and try to detect where it went wrong. For example if a section following a in line equation is all formatted like an equation, then you've missed a $

But if the delimiter I'm hunting is a brace, as you're asking about, I use either the build in high light tool in TeXmaker or TeXnicCenter on windows or TexMaker on linux. If I have selected a brace it will light up the corresponding brace, that way I'll have to go through the entire document. The portion of the doc to be hunted in can be trimmed by commenting sections out, like you said, starting from the top of the doc (in my experience, the missing brace is the closing brace and almost never the starting brace)

I'm sorry but some great tool for this would be much appreciated.

0

In LuaTeX, it is possible to determine where a "runaway argument" starts from, to some extent.

Use \tracingmacros=1 and https://tex.stackexchange.com/a/632367/250119 (my answer) to print each line as it's read by TeX:

%! TEX program = lualatex
\documentclass{article}
\usepackage{currfile}
\usepackage{luacode}
\begin{luacode*}
luatexbase.add_to_callback('process_input_buffer', function()
    texio.write("log", tex.inputlineno .. "|" .. token.get_macro("currfilename") .. "\n")
end, "function to print current file and line number")
\end{luacode*}

\begin{document}
\tracingmacros=1

\long \def \a #1 {}

\a {content content
    content...



\end{document}

The output would contain e.g.

59|ts1cmr.fd
60|ts1cmr.fd
61|ts1cmr.fd
62|ts1cmr.fd
63|ts1cmr.fd
)
LaTeX Font Info:    ... okay on input line 11.
LaTeX Font Info:    Checking defaults for TU/lmr/m/n on input line 11.
LaTeX Font Info:    ... okay on input line 11.
LaTeX Font Info:    Checking defaults for OMX/cmex/m/n on input line 11.
LaTeX Font Info:    ... okay on input line 11.
LaTeX Font Info:    Checking defaults for U/cmr/m/n on input line 11.
LaTeX Font Info:    ... okay on input line 11.
12|a.tex
13|a.tex
14|a.tex
15|a.tex
16|a.tex

\a #1 ->
17|a.tex
18|a.tex
19|a.tex
20|a.tex
21|a.tex
)
Runaway argument?
{content content content... \par \par \par \end {document} 
! File ended while scanning use of \a.
<inserted text> 
\par 
<*> a.tex

Look for the last line with ->. Then look for the line number around it.

Side note, \tracingonline=1 can be used as well to print to the terminal, but terminal tend to be slower than files.

This technique also works when it's delimited argument instead of brace mismatching (especially useful in verbatim-like environments, because those tend to be able to grab multiple physical lines):

%! TEX program = lualatex
\documentclass{article}
\usepackage{currfile}
\usepackage{luacode}
\begin{luacode*}
luatexbase.add_to_callback('process_input_buffer', function()
    texio.write("log", tex.inputlineno .. "|" .. token.get_macro("currfilename") .. "\n")
end, "function to print current file and line number")
\end{luacode*}

\begin{document}
\tracingmacros=1

\long \def \a #1\b{}

\a content content
    content...



\end{document}
LaTeX Font Info:    ... okay on input line 11.
LaTeX Font Info:    Checking defaults for U/cmr/m/n on input line 11.
LaTeX Font Info:    ... okay on input line 11.
12|a.tex
13|a.tex
14|a.tex
15|a.tex
16|a.tex

\a #1\b ->
17|a.tex
18|a.tex
19|a.tex
20|a.tex
21|a.tex
)
Runaway argument?
content content content... \par \par \par \end {document} 
! File ended while scanning use of \a.
<inserted text> 
\par 

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .