Claude CodeでLaTeXのコンパイルエラーを.logから直す手順
latexmkのコンパイルが止まったとき、.logの「!」行と「l.12」の行番号だけをClaude Codeに渡して原因行を直させる手順です。Missing $ insertedは報告行より前に原因がある点も扱います。
LaTeXのコンパイルエラーは、.log に出る「!」で始まる行と、その直後の「l.12」という行番号の組を拾えば、原因の行までたどれます。この2点だけをClaude Codeに渡せば、数百行あるログ全体を貼らなくても修正まで進められます。
latexmkは、LaTeX文書の生成に必要なコマンドの順序を自動で実行するツールです。CTANの説明では、TeX LiveとMiKTeXの両方に含まれるとされています。ここではlatexmkでコンパイルし、失敗したログをClaude Codeの非対話モード(claude -p)に渡す流れを組みます。
エラーを直すまでの流れ
- 1
コンパイルして止める
latexmk -pdf -interaction=nonstopmode main.texを実行し、main.logを残します。 - 2
エラー部分だけ抜く
!で始まる行と、その後ろ数行をgrepで取り出します。 - 3
Claude Codeに原因行を探させる
抜いたログを
claude -pに渡し、l.12が指す行をmain.texで確認して直させます。 - 4
再コンパイルする
!の行が消えるまで繰り返します。回数には上限を付けます。
latexmkを止めずに.logを残す — -interaction=nonstopmode
TeXはエラーに当たると、既定では端末に ? を出して入力を待ちます。人がいない実行では、ここで止まったように見えます。latexmkのマニュアルは、エラーのあとにLaTeXを入力待ちで止めたくないときは -interaction=nonstopmode を渡すよう書いています。latexmkがこれをLaTeX側へそのまま渡します。
latexmk -pdf -interaction=nonstopmode main.tex-pdf はpdflatexでPDFを作るオプションです。LuaLaTeXやXeLaTeXなら -lualatex や -xelatex を使います。
もう1つ、-f というオプションがあります。これはエラーがあっても後続の処理を続けさせるものです。-f を付けないと、原因が後続の処理では解消しないエラーを検出した時点でlatexmkは先へ進みません。ログ調査では、最初のエラーで止まってくれる方が読む量が減るので、-f は付けません。
なお、未定義の参照や引用、重複して定義された参照は、latexmkではエラーでなく警告として扱われます。! の行がなくても、PDFに「?」が残ることがあるのはこのためです。原因の探し方は後の節で扱います。
.logの「!」行と「l.12」行の読み方
エラーは .log の中で、決まった形で出ます。Overleafのドキュメントに載っている、\alpha を \Zlpha と打ち間違えた例がわかりやすい形です。
! Undefined control sequence.
<recently read> \Zlpha
l.10 A typo when writing $\alpha$ could be $\Zlpha
$読むところは3か所です。
!の行がエラーの種類です。ここではUndefined control sequence(未定義のコマンド)です<recently read>などの行は、直前に読んでいたコマンドです。ここに怪しい名前が出ますl.10は、TeXがその時点で読み込み中だったソースの行番号です。後ろにその行の途中までが写ります
l.10 の「l」は行(line)の意味で、main.tex の10行目と考えてよい場合がほとんどです。ただし\inputや\includeで分割している文書では、行番号は読み込み中の子ファイルの中のものです。子ファイルの名前は、ログ内の括弧つきのファイル名から追う必要があります。依頼文には「分割ファイルがある場合は \input の入れ子をたどって」と書き添えておきます。
Missing $ insertedは報告行より前に原因がある
l.N はあくまで「TeXが気づいた行」で、「誤りを書いた行」とは限りません。これがもっとも取り違えやすい点です。
Overleafの Missing $ inserted のページには、ディスプレイ数式 $$ の中に \par を書いた例があります。ログは次のように、複数のエラーを続けて出します。
! Missing $ inserted.
<inserted text>
$
l.12 $$y=f(x)\par
$$
I've inserted a begin-math/end-math symbol since I think
you left one out. Proceed, with fingers crossed.
! Display math should end with $$.
<to be read again>
\par
l.12 $$y=f(x)\par
$$
! Missing $ inserted.
<inserted text>
$
l.13 \end{document}最後のエラーは l.13 \end{document} を指しますが、原因は12行目の数式です。数式の中に \par があったため、TeXは「$ が抜けている」と判断して補いました。その状態が最後の行まで続いています。
この型のエラーでは、ログに複数の ! が並びます。最初のエラーを直せば、後ろのエラーは消えることが多いです。Claude Codeには次のように頼むと、最後の行だけを直して別のエラーを生む失敗を避けやすくなります。
最初の
!のエラーだけを対象にしてください。l.の行とその少し前をmain.texで読み、原因を説明してから直してください。
Overleafが挙げる Missing $ inserted の主な原因は、数式用のコマンドを数式の外で使った場合、_ のような数式用の文字をファイル名やURLの中で使った場合、数式内で使えないコマンドを使った場合、数式中に空行を入れた場合です。ログを渡すときに「このうちどれかを疑って」と添えると、探す範囲が狭くなります。
Undefined control sequenceはタイプミスとパッケージ漏れを分ける
Undefined control sequence の原因は、大きく2つです。Overleafのページは、コマンドのタイプミスと、必要なパッケージを読み込み忘れた場合を挙げています。例として、\xspace を使っているのに \usepackage{xspace} がない文書が載っています。
切り分けは、エラーの行にあるコマンド名を見ればできます。
| ログのコマンド名 | 疑うこと | 直し方 |
|---|---|---|
\Zlpha のように既存のコマンドに似ている | 疑うことタイプミス | 直し方正しい綴りに直す |
\xspace のように実在するコマンド | 疑うことパッケージの読み込み漏れ | 直し方プリアンブルに \usepackage{...} を足す |
Claude Codeに頼むときは、「実在するコマンドか、タイプミスかを先に判定してください」と書きます。タイプミスを \usepackage で埋めようとする直し方を防げます。
File `xxx.sty' not foundは.texを直すエラーではない
! LaTeX Error: File xxx.sty' not found. は、\usepackage は書いてあるのに、パッケージのファイルが手元のTeX環境に入っていない状態です。\usepackage の漏れとは向きが逆で、main.texに原因はありません。ここでClaude Codeが\usepackage` の行を消すと、エラーは消えても、そのパッケージの機能を使う箇所が別のエラーになります。
見分けは、! の行にファイル名が出ているかどうかです。latexmkのマニュアルにも、latexmkは .log からこの種の「ファイルを探したが無かった」という報告を拾って扱う、という説明があります。このエラーを渡すときは、依頼文に「\usepackage は消さず、足りないパッケージ名だけを教えて」と書いておきます。パッケージを入れる作業は、手元のTeX環境側の操作です。
参考文献の「?」は.blgを見る
[?] や (?) がPDFに残る原因は、main.log に ! の行が出ないことが多く、先の自動ループは「エラーなし」で終わってしまいます。前の節で触れたとおり、未定義の引用はlatexmkでは警告の扱いです。
BibTeXやbiberの側のエラーは main.log でなく、main.blg に出ます。latexmkのマニュアルも、.log と並べて .blg を生成ファイルの一つに挙げています。引用が解決しないときは、grep -i -E 'error|warning' main.blg で .bib の書式の誤りや、見つからない文献キーを確かめます。main.log と main.blg の両方の抜粋を渡し、「引用キーが .bib にあるか」を先に調べさせます。
なお、-Werror を付けると、未定義の引用や参照が最後の実行に残ったとき、latexmkが0以外の終了コードを返します。参照の警告を終了コードで拾いたいときの選択肢です。
Overfull hboxは別の依頼にする
Overfull \hbox は、行が余白からはみ出した警告です。ここで組む自動ループは、! で始まる行だけを数えます。Overfull の行は ! で始まらないので、ループの終了判定には入りません。
警告まで同じ依頼に混ぜると、Claude Codeはエラーを直すと同時に文章の組み方まで変えてしまい、差分が読みにくくなります。まず ! の行がゼロになるまで直し、そのあとで「Overfullの警告が出ている段落を、本文の意味を変えずに調整して」と別に頼みます。手元のログに Overfull が何行あるかは、grep -c Overfull main.log で数えられます。
ログを絞ってclaude -pに渡す
Claude Codeは、標準入力から受け取った内容を処理できます。公式のヘッドレスモードの説明にも、ビルドログをパイプで渡して原因を説明させる例があります。
grep -A4 '^!' main.log | head -60 | claude -p \
"このLaTeXのエラーの原因行を main.tex で確認して直して" \
--allowedTools "Read,Edit"grep -A4 '^!' は、! の行とその後ろ4行を取り出します。上のログ例のとおり、<recently read> と l.10 の行は、! の行から数行以内に収まります。head -60 は、エラーが大量に出たときに、渡す量を抑えるための上限です。
標準入力の上限は10MBで、超えると非対話モードはエラーで終了します。LaTeXのログは数百KBに収まることが多いので、上限に当たるのは珍しい場合ですが、grep で絞る方が安く速く済みます。
--allowedTools "Read,Edit" は、確認なしで読むことと編集することを許す指定です。Bash は入れていません。再コンパイルは、Claude Codeではなくスクリプト側が担当するためです。
3回まで回す自動ループ
エラーが連鎖するときは、1回では直りません。コンパイルと修正を繰り返すスクリプトにします。次の例は、公式のオプションとlatexmkの引数を組み合わせた一例です。手元の環境で動かして確かめてください。
#!/bin/bash
# fix-tex.sh — 最大3回まで、コンパイルと修正を繰り返す
rm -f main.log
for i in 1 2 3; do
latexmk -pdf -interaction=nonstopmode main.tex >/dev/null 2>&1
if ! grep -q '^!' main.log; then
echo "エラーなし(${i}回目)"; exit 0
fi
grep -A4 '^!' main.log | head -60 | claude -p \
"最初の ! のエラーだけを対象に、l.行番号が指す行を main.tex で
確認して原因を直して。実在するコマンドなら usepackage 漏れを先に疑う" \
--allowedTools "Read,Edit"
done
echo "3回で直りませんでした。main.log を確認してください"; exit 1ここでの設計は3点です。
- 成功の判定は、latexmkの終了コードではなく、
main.logに!で始まる行があるかどうかです。警告だけの文書でもループが止まります - 毎回、最初の
!だけを対象に頼みます。連鎖したエラーは、最初を直すと消えることが多いためです - 回数に上限を付けています。直らないエラーで課金が続く事態を防ぎます
--allowedTools に Read,Edit しか入れていないので、Claude Codeが別のコマンドを実行しようとすると、許可を確認する相手がいないため拒否されます。実行の許可の仕組みは、公式のヘッドレスモードの説明に書かれています。Claude Codeに再コンパイルまで任せたいときは、Bash(latexmk *) のようにコマンドを絞った許可を足します。
つまずきやすい点
落とし穴
古い main.log を読んでしまう
前回のログが残っていると、今回の失敗を前回のログと取り違えるおそれがあります。上のスクリプトは、ループの前に rm -f main.log を実行して、読み違いを避けています。
出力先を -outdir=build のように変えている場合は、ログも build/main.log に出ます。grep のパスを合わせてください。
ほかの言語のビルドエラーでも、出力を絞って渡す考え方は同じです。Xcodeの場合はxcodebuildのエラーを-quietとxcresultで絞る手順にまとめています。
まとめ
LaTeXのエラーは、! の行と l.N の組が原因行への入口です。ただし l.N は「TeXが気づいた行」なので、Missing $ inserted のように手前に原因がある場合があります。最初のエラーだけを頼み、実在するコマンドならパッケージ漏れを先に疑わせると、修正の精度が上がります。
自動ループは、! の有無を終了条件にして回数に上限を付けた形で組めます。Overfull hboxは別の依頼にします。PDFのアクセシビリティ検証の流れはPDF/UAのveraPDF違反を直す記事に、日本語縦書き文書のひな型は縦書きPDFへの変換手順にあります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。