Claude Media
Claude CodeでLaTeXのコンパイルエラーを.logから直す手順

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. 1

    コンパイルして止める

    latexmk -pdf -interaction=nonstopmode main.tex を実行し、main.log を残します。

  2. 2

    エラー部分だけ抜く

    ! で始まる行と、その後ろ数行を grep で取り出します。

  3. 3

    Claude Codeに原因行を探させる

    抜いたログを claude -p に渡し、l.12 が指す行を main.tex で確認して直させます。

  4. 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への変換手順にあります。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. code.claude.com/docs/en/headless
  2. ctan.org/pkg/latexmk
  3. mirrors.ctan.org/support/latexmk/latexmk.txt
  4. overleaf.com/learn/latex/Errors/Undefined_control_sequence
  5. overleaf.com/learn/latex/Errors/Missing_$_inserted
この記事を共有:XはてブLinkedIn