Undefined control sequence

! Undefined control sequence は、ほとんどの人が最初に出会う LaTeX のエラーです。ただし厳密には LaTeX のエラーではありません。LaTeX を一切読み込まない素の TeX でも同じ三語がそのまま出ます——control sequence(制御綴)は「バックスラッシュに続く名前」を指す TeX 自身の用語で、メッセージは「その名前は辞書に無い」としか言っていないのです。それでもこれが検索のいちばん多いエラーである理由は、その先で起きることにあります。TeX は止まりません。知らないコマンドを黙って捨て、そのまま読み進め、引数が本文の文字に化けた PDF を平然と渡してきます。このページでは、ほぼ全てを占める 3 つの原因——綴り間違い、読み込んでいないパッケージ、定義より前に使ったマクロ——と、ログの行番号が「TeX が気づいた場所」であって間違えた場所とは限らない、という罠を扱います。

エラーの読み方——行が折り返された位置が犯人

折り返された 2 行のうち、上の行の末尾にあるコマンドが未定義のコマンドです。 TeX はエラーを報告するとき、その行を「すでに読んだ部分」と「まだ読んでいない部分」に割って上下に並べます。読むのを止めた瞬間が問題の起きた瞬間なので、境目がそのまま犯人を指します。下は \textbf\textbnf と打ち間違えた本物のログです。

terminal
! Undefined control sequence.
l.4 This is \textbnf
                    {bold} text.

l.4 は 4 行目という意味です。数式の中で起きた場合は、l.4 の上に <recently read> \fra のような行が増えることがあり、こちらはコマンド名を単独で示してくれます。いずれにせよ、まずすべきは そのコマンド名を自分のソースで検索すること。綴りが正しければ次の節へ進みます。なお、パッケージ名のほうを打ち間違えた場合はこのエラーにはならず、! LaTeX Error: File に続けて見つからない .sty の名前が出る別のエラーになります。

原因は 3 つしかない——綴り・パッケージ・定義の順番

未定義コマンドの原因は、実務上ほぼこの 3 つに尽きます。綴り間違い、パッケージの読み込み忘れ、定義より先に使ったマクロ。 順番も重要で、上から順に潰すのがいちばん速い——綴りの確認は数秒で済み、パッケージの確認はプリアンブルを見るだけ、マクロの確認だけが少し手間だからです。

  • 綴り間違い——\fra\frac\textbnf\textbf\begni\begin。コマンド名は大文字小文字を区別するので、\LaTeX\Latex と書いても未定義になります。
  • パッケージの読み込み忘れ——コマンドの綴りは合っているのに、それを定義するパッケージをプリアンブルで \usepackage していない。次節の対応表を参照してください。
  • 定義より先に使ったマクロ——\newcommand の書き忘れ、定義行より上での使用、あるいは定義が波括弧や環境の中にあってその外では消えている。

そのコマンドはどのパッケージのものか

下の表は、この理由で未定義になりやすいコマンドと、それを定義するパッケージの対応です(TeX Live 2024 で \ifdefined により実地に確認したもの)。もっとも多い取り違えは amsmathamssymb です。 \lVertamsmath にあって amssymb には無く、\mathbb\thereforeamssymb にあって amsmath には無い——数式まわりで「読み込んでいるのに未定義」が起きたら、まずここを疑ってください。表に無いコマンドは texdoc パッケージ名 でそのパッケージの説明書を開いて確かめられます。

命令パッケージ備考
\includegraphicsgraphicx画像の読み込み。未読込だとオプションが本文に印字される
\toprulebooktabs\midrule\bottomrule も同じ
\lVertamsmathamssymb には無い\rVert も同じ
\mathbbamssymbamsmath だけでは出ない(実体は amsfonts
\thereforeamssymb\because も同じ。amsmath には無い
\bmbm数式の太字。\boldsymbolamsmath
\coloneqqmathtoolsamsmath を読み込むだけでは足りない
\multirowmultirow表のセルの縦結合
\FloatBarrierplaceins図表をここより先に流さない
\hrefhyperref\url だけなら url でも足りる
\textcolorxcolor\definecolor\colorbox も同じ
\SIsiunitx新しい書き方は \qty。どちらも同じパッケージ

\newcommand が効かない——順番とスコープ

TeX は上から下へ一度だけ読むので、定義は使用より前になければなりません。 人間はソースを「全体」として眺めますが、TeX は行を順に読み、\newcommand に到達した瞬間にはじめてその名前を辞書に登録します。だから 200 行目で定義したマクロを 40 行目で使えば未定義です。もう一つの落とし穴が スコープ——波括弧や環境の内側で定義したマクロは、その閉じ括弧で消えます。どちらの事故もプリアンブルに定義をまとめれば起きません。\newcommand 自体の書き方(引数、既定値、\renewcommand との違い)は「マクロの定義」のページが扱います。

latex
\documentclass{article}
\begin{document}
% too early: \R is not in the dictionary yet
$\R$
\newcommand{\R}{\mathbb{R}}

% scoped: \tmp dies at the closing brace
{\newcommand{\tmp}{scoped}\tmp}
\tmp
\end{document}

報告された行が間違いの場所とは限らない

l.NN の上に -> を含む行があれば、間違いはその行に書かれたマクロの中にあります。 l.NN はあくまで TeX が異常に気づいた場所——つまりマクロを使った行です。定義そのものは数百行離れていることも、パッケージの中にあることもあります。次の例では、\lVert を使う \mynorm\mysq が呼んでおり、amsmath を読み込み忘れています。ログが \mynorm #1->\lVert と示すのが唯一の手がかりです。

terminal
! Undefined control sequence.
\mynorm #1->\lVert
                   #1 \rVert
l.5 The value $\mysq{x}
                       $ is here.

この例では \mysq の名前がログに出ていません。LaTeX が \errorcontextlines-1 に設定している(latex.ltx の 535 行目)ため、マクロの呼び出し連鎖のうち いちばん内側の一段しか表示されない からです。パッケージ内部のマクロで転んだときはこれでは足りません。プリアンブルに \errorcontextlines=999 を置いて組み直すと、\mysq #1->\mynorm {#1} の行が加わり、呼び出しの経路が全部見えます。原因が分かったら消しておくのが実務——普段は静かなログのほうが読めます。

PDF はできてしまう——それが本当の危険

未定義のコマンドは組版を止めません。TeX はそのコマンドだけを捨て、続きをふつうの文字として組みます。 つまり graphicx を読み込み忘れて \includegraphics[width=3cm]{example-image} と書くと、画像が消えるだけでなく、オプションとファイル名が 本文として印字された PDF が出来上がります。エディタやビルドツールは既定でエラーがあっても走り続ける設定(-interaction=nonstopmode)なので、警告の山を素通りして「できた PDF」を提出してしまう事故はこれで起きます。未定義コマンドが 1 つでも残っていたら、その PDF は信用してはいけません。

latex
% graphicx was never loaded
\includegraphics[width=3cm]{example-image}

% the run still succeeds, and this is what lands on the page:
%   [width=3cm]example-image