LaTeX のエラーメッセージが読みにくいのは、それがスタックトレースではないからです。! Undefined control sequence に続く二行は「どの命令が悪いか」の説明ではなく、TeX の読み取りヘッドが止まった瞬間の写真——上の行が読み終えた分、下の行がまだ読んでいない分で、その切れ目こそが事故現場です。この見方さえ手に入れば、l.NN の行番号がときどき嘘をつく理由も、? プロンプトで h と x のどちらを打つべきかも、.log に端末より多くのことが書いてある理由も、すべて同じ一つの仕組みから説明できます。このページはエラーメッセージの構造、-file-line-error と -interaction の各モード、ログの見方、そして原因を二分探索で追い込む手順を扱います。
エラーメッセージの構造——! の行と l.NN の二段組
! の行が「何が起きたか」、l.NN から始まる二段が「どこで止まったか」を言います。そして原因はほぼいつも、上の段の一番右端にあります。 TeX は入力行を、読み終えた部分と未読の部分に切って上下に積み、切れ目を字下げで表現します。下の例なら上段の末尾が \textbnf ——つまり読んだ瞬間に事故が起きた命令そのものです。{bold} text. はまだ触っていないので下段に残っています。この「切れ目が犯人を指す」性質は、行番号よりずっと信用できます。行番号は「気づいた場所」ですが、切れ目は「読んでいた場所」だからです。
! Undefined control sequence.
l.3 This is \textbnf
{bold} text.
? l.NN の上に別の行が挟まることがあり、これがエラーの「文脈」です。\mynorm #1->\lVert のように -> を含む行は「その命令の展開の途中で起きた」、<inserted text> は「TeX が復旧のために自分で補った字」、<to be read again> は「いったん読んで押し戻した字」、<read *> は「端末からの入力を待っている」ことを意味します。行が長すぎて端末に収まらないときは先頭が ... で省略されるので、l.9 ...: $\frac{1}{2}$ and a stray \undefinedmacro のような表示を見たら、その行の実際の先頭はもっと左にあると考えてください。
| 文脈の行 | 何を意味するか |
|---|---|
l.NN | 読んでいた入力行。上下の切れ目が停止位置 |
\mac #1-> | \mac の展開の中で起きた。定義は別の場所にある |
<inserted text> | TeX が復旧のために自分で補った字($ など) |
<recently read> | 直前に読み込んだ字。多くはそれ自体が原因 |
<to be read again> | いったん読んで押し戻した字。次に読み直される |
<argument> | 引数の中で起きた。呼び出し側ではなく引数を見る |
<read *> | 端末からの入力待ち。非対話モードだと即座に打ち切られる |
l.NN が 1 行ずれる本当の理由
\usepackage が出すエラーは、たいてい実際より 1 行あとに報告されます。原因は \usepackage の末尾に置ける省略可能な日付引数です。 \usepackage[opt]{pkg}[2021/02/14] という書式が許されているため、TeX は } を読んだあとで「次に [ が来るか」を覗きに行きます。この先読みは空白と改行を読み飛ばすので、次の行まで到達してしまい、エラーの報告位置がそこになります。TeX Live 2024 で実測すると、\usepackage[latin1]{inputenc} を 3 行目に置いたときのオプション衝突は l.4 と報告され、同じ行の末尾に [2021/02/14] を明示的に足すと l.3 に変わります。つまり、パッケージ関連のエラーで示された行が空行や \begin{document} だったら、一つ上の行を見てください。
% \usepackage[latin1]{inputenc} sits on line 3 -- reported at line 4
./oc1.tex:4: LaTeX Error: Option clash for package inputenc.
l.4 \begin
{document}
% same source, but the optional date argument is written out
% -- the look-ahead ends on line 3, and so does the report
./ocA.tex:3: LaTeX Error: Option clash for package inputenc.
l.3 \usepackage[latin1]{inputenc}[2021/02/14]同じ「気づいた場所」と「原因の場所」のずれは、閉じ忘れた } でも起こります。こちらは 1 行ではなく数十行ずれることがあり、TeX は最終的に段落の終わりや \end{document} で音を上げます。個々の症例——数式モードの取りこぼし、未定義命令、} の不足——は専用ページが持っているので、そちらを参照してください。ここで押さえるべきは一般則だけです:行番号が正しく見えるときほど、疑うべきは上流。
-file-line-error — エディタが読める形式にする
-file-line-error を付けると、先頭の ! が ./file.tex:3: に置き換わります。これだけで、どのファイルの何行目かが一行に収まり、エディタや CI がそのままジャンプできます。 既定の形式には致命的な欠落があって、l.3 は行番号しか言わず、ファイル名はずっと上のほうにある (./chapters/intro.tex という括弧開きから推測するしかありません。章を \input で分割した文書では、これが実務上いちばん時間を食います。-file-line-error はその推測を消します。l.NN の二段組はそのまま残るので、失うものは何もありません。
$ pdflatex main.tex
(./chapters/intro.tex
! Undefined control sequence.
l.2 Here is \nosuchcmd
in a chapter.
$ pdflatex -file-line-error main.tex
(./chapters/intro.tex
./chapters/intro.tex:2: Undefined control sequence.
l.2 Here is \nosuchcmd
in a chapter.多くの環境では、この形式がすでに既定になっています。latexmk は内部で有効にし、TeXworks や VS Code の LaTeX Workshop などのフロントエンドも標準で付けます。自分で叩くときは -file-line-error を、明示的に切りたいときは -no-file-line-error を渡してください。なお、エラーの発生源がパッケージのときは表示されるパスがそのパッケージのファイルになります——/usr/local/texlive/…/foo.sty:120: と出たら、それはあなたのファイルの問題ではなく、foo が文句を言っているという意味です。
? プロンプトの返事——h・i・x・q・r・s と Enter
? で止まったときの返事は 9 種類あり、? を打てば TeX 自身がその一覧を印字します。 これは既定の errorstopmode の動作で、TeX が「どうしますか」と尋ねているところです。実務でいちばん使うのは Enter(このエラーを無視して続行)、h(TeX 自身のヘルプ文を表示)、x(即座に打ち切り、PDF は作られない)の三つ。長い文書で残りのエラーもまとめて見たいときは r か s を打って走らせ切り、あとから .log を読むのが早道です。
? ?
Type <return> to proceed, S to scroll future error messages,
R to run without stopping, Q to run quietly,
I to insert something, E to edit your file,
1 or ... or 9 to ignore the next 1 to 9 tokens of input,
H for help, X to quit.
?| 返事 | TeX が何をするか |
|---|---|
Return | このエラーをなかったことにして続行する。組版は続き、PDF もできる |
h | そのメッセージ専用のヘルプ文を印字する。.log には最初から入っている |
i | その場に文字列を差し込む。i\textbf で綴り違いをその実行だけ直せる |
x | 即座に打ち切る。No pages of output. と出て PDF は作られない |
q | OK, entering \batchmode と表示し、以後は端末に何も出さずに走り切る |
r | OK, entering \nonstopmode... と表示し、以後止まらず走り切る |
s | OK, entering \scrollmode...。止まらないが端末入力は受け付ける |
e | 環境変数 TEXEDIT に設定したエディタを、その行で開く |
1 … 9 | 次の 1〜9 個のトークンを捨てて続行。捨てた直後の行が再表示される |
-interaction の 4 つのモード——どれをいつ使うか
pdflatex --help が挙げる値は batchmode / nonstopmode / scrollmode / errorstopmode の 4 つで、規定は errorstopmode。スクリプトから呼ぶなら -interaction=nonstopmode、CI で端末を汚したくないなら -interaction=batchmode です。 四者を分けているのは「止まるか」と「端末に書くか」の二軸だけで、いちばん誤解されやすいのは scrollmode と nonstopmode の違いです。実測すると、\typein で入力を求める文書を scrollmode で走らせると端末からの入力をちゃんと読み、nonstopmode では ! Emergency stop. で落ちます。つまり境目はエラーではなく端末入力にあります。
| モード | 止まるか・端末に書くか |
|---|---|
errorstopmode | 既定。すべてのエラーで ? に止まって尋ねる。手で追うとき向き |
scrollmode | エラーでは止まらないが、端末入力は読む。全文を流し見したいとき |
nonstopmode | 端末入力を一切しない。求められたら ! Emergency stop. で終わる |
batchmode | nonstopmode に加えて端末出力も止める。.log は完全に書かれる |
batchmode が「何も出さない」というのは、正確にはほぼ何も出さない、です。TeX Live 2024 で同じエラー入りの文書を走らせて計ると、端末出力は nonstopmode の 1212 バイトに対し batchmode は 144 バイト——残るのは pdfTeX のバナーと entering extended mode だけで、これらは対話モードが効き始める前に印字されるからです。一方 .log はどちらも 4144 バイトで完全に同一、PDF も同じように生成されます。つまり batchmode は情報を捨てているのではなく、端末に流していないだけ。CI ではこれを使い、判定は次節の終了コードで行い、詳細は .log を回収して読むのが定石です。この 4 つはコマンドラインオプションであると同時に TeX のプリミティブでもあるので、\nonstopmode のように文書の先頭に書いても同じ効果になります。
-halt-on-error と終了コード
-halt-on-error は最初のエラーで実行を打ち切ります。 TeX Live 2024 で確認すると、最初の ! Undefined control sequence の直後に ! ==> Fatal error occurred, no output PDF file produced! を出して終了し、PDF は残りません。同じ文書を -interaction=nonstopmode だけで走らせると 4 件のエラーを全部報告したうえで PDF まで作るので、「壊れているのに成功したように見える」事故を防ぎたいときに効きます。終了コードも実測しました:エラーが 1 件でもあれば 1、無ければ 0。これはモードに依存せず nonstopmode でも batchmode でも同じで、警告は終了コードを変えません。つまり Makefile や CI で pdflatex && … と書いたときに止まるのはエラーだけです。
# interactive: stop at the first error and look at it
pdflatex -file-line-error -halt-on-error document.tex
# CI: quiet terminal, full log on disk, exit status decides
pdflatex -interaction=batchmode -halt-on-error -file-line-error document.tex
echo $? # 1 if any error occurred, 0 if none.log の見方——端末より多くのことが書いてある
.log には、端末に出なかったヘルプ文がそのまま書かれています。だから「メッセージの意味がわからない」と思ったら、h を打ち直す必要はなく .log を開けば済みます。 実測では、同じ実行で端末に流れたのが 938 バイト、.log は 3199 バイト。差の大部分がこのヘルプ文です。効き目がいちばん大きいのはオプション衝突で、端末には ! LaTeX Error: Option clash for package inputenc. としか出ませんが、.log には「どのオプションで先に読み込まれ、いま何を要求したか」が具体的に書かれています。この 4 行があるかないかで、原因追及の手間はまったく変わります。
% only the first line of this reaches the terminal
./oc1.tex:4: LaTeX Error: Option clash for package inputenc.
...
The package inputenc has already been loaded with options:
[utf8]
There has now been an attempt to load it with options
[latin1]
Adding the global options:
utf8,latin1
to your \documentclass declaration may fix this.ログ全体の構造も覚えてしまうと速くなります。先頭行にエンジン名・バージョン・実行日時、次に **document.tex という起動引数、そこから先は括弧の入れ子です——( でファイルを開き ) で閉じるので、あるパッケージがどのファイルの中から読み込まれたかは括弧のネストが答えになります。[1] [2] は組み上がったページの出力、末尾は Here is how much of TeX's memory you used: に続くメモリ集計と Output written on document.pdf (1 page, 12817 bytes). です。この構造を丸ごと相手にしたくなければ、TeX Live 同梱の texfot を挟むと、エラー・警告・最終行だけに絞り込んだ出力になります。
$ texfot pdflatex -interaction=nonstopmode two.tex
texfot: invoking: pdflatex -interaction=nonstopmode two.tex
This is pdfTeX, Version 3.141592653-2.6-1.40.26 (TeX Live 2024)
! Undefined control sequence.
l.3 First \foo
! Missing $ inserted.
<inserted text>
l.4 Second \bar
Output written on two.pdf (1 page, 23091 bytes).\listfiles と *File List* — 実際に読み込まれたものを数える
プリアンブルのどこかに \listfiles を一行足すと、.log の末尾に *File List* という表が付き、読み込まれたすべてのファイルが日付・バージョン・一行説明つきで並びます。 TeX Live 2024 で数えると、素の article は 3 ファイル(article.cls、size10.clo、l3backend-pdftex.def)。ここに hyperref を 1 行足すだけで 33 ファイル——つまり hyperref は単独で 30 個を引き連れてきます。tikz なら 34 ファイル。「読み込んだ覚えのないパッケージが衝突している」という状況で最初に打つ手がこれです。 質問を投稿するときやバグ報告のときにも、この表を貼れば環境の食い違いがひと目で伝わります。
% \listfiles goes anywhere in the preamble; this lands at the end of the .log
*File List*
article.cls 2023/05/17 v1.4n Standard LaTeX document class
size10.clo 2023/05/17 v1.4n Standard LaTeX file (size option)
amsmath.sty 2023/05/13 v2.17o AMS math features
hyperref.sty 2024-01-20 v7.01h Hypertext links for LaTeX
iftex.sty 2022/02/03 v1.0f TeX engine tests
***********もう一段細かく見たいときは -recorder を付けます。実行のあいだに開いたすべてのファイルが .fls に INPUT 行として記録され、tikz を 1 つ読み込んだだけの文書でも 140 行になります。\listfiles が「読み込まれたパッケージの一覧」を答えるのに対し、.fls は「触れたファイルの一覧」——フォントの .tfm や設定ファイルまで含みます。パッケージの衝突を追うときは前者、kpathsea がどこを見に行ったかを追うときは後者が向いています。
\show / \showthe / \typeout — TeX の頭の中を覗く
\show\foo は \foo の定義を、\showthe\textwidth は長さやカウンタの値を印字します。 出力は .log に > \LaTeX=macro: や > 345.0pt. の形で残り、行頭の > がその印です(ちなみに 345.0pt は article の既定の \textwidth)。「このコマンド、いまどう定義されているのか」がわからなくなったら、推測せず \show を打つのがいちばん速い——再定義しているのがクラスなのかパッケージなのかは、たいていこれで判明します。自分でメッセージを出したいときは \typeout{…} と \message{…} があり、実測すると \typeout は独立した行に、\message は現在の行の続きに書き込みます。printf 風のデバッグでは前者が読みやすく、ページ番号の隣に印を出したいときは後者が便利です。
\show\LaTeX % > \LaTeX=macro: ... (definition follows)
\showthe\textwidth % > 345.0pt. (article default)
\typeout{reached the theorem} % own line in log and terminal
\message{mark} % appended to the current line
\tracingall % dump every step to the log -- extremely verbose最後の手段が \tracingall で、TeX が行うすべての操作——マクロ展開、モードの変化、行分割の試行——をログに書き出します。数ページの文書でも数十 MB になるので、原則として問題の直前に置いて直後で \tracingnone に戻すか、trace パッケージ(出力を読みやすく整えます)と組み合わせて使ってください。\tracingall は「どのマクロが悪さをしているか」ではなく「どの順番で起きたか」を知りたいときの道具です——順番さえわかれば、たいてい \show に戻って一点を確かめれば済みます。
二分探索で犯人を絞る——\end{document} を上に動かす
メッセージだけでは原因がわからないときは、文書を半分に切って走らせるのが最短です。本文の途中に \end{document} を書き足すだけで、それより後ろは丸ごと無視されます。 TeX Live 2024 で確認したとおり、\end{document} の後ろに何が書いてあっても——壊れた命令であっても——読まれません。だから元の \end{document} を消す必要すらなく、追加した一行を上下に動かすだけで挟み撃ちにできます。10 回も動かせば 1000 行の文書が 1 行に絞れる計算です。プリアンブルが疑わしいときは \usepackage の行を半分ずつ % でコメントアウトし、\include で章を分けているなら \includeonly{chapter3} を使います。
\begin{document}
\input{chapters/intro}
\input{chapters/method}
\end{document} % <- added: bisect here, everything below is ignored
\input{chapters/results}
\input{chapters/discussion}
\end{document}半分に絞れたら、そのまま必要最小限まで削り続けるのが定石です。\usepackage を一つずつ外し、本文を段落単位で捨て、画像は graphicx に同梱の example-image に、長文は lipsum に置き換えていくと、最後に残るのは十数行になります。ここまで縮めば原因はほぼ自明になりますし、それでもわからなければ、その十数行がそのまま質問に貼れる最小構成になります。縮める作業そのものが診断です——質問として投稿する際の作法(どこに聞くか、何を添えるか)は「コミュニティ」のページが扱っています。