LaTeX でエラーが出たら最小の再現コード例を作ろう

<!-- # LaTeX でエラーが出たら最小の再現コード例を作ろう -->

LaTeX でエラーが出た際、どのようにエラーの解消に取り組むでしょうか。エラー文の 1 つ 1 つを読んで愚直に解消していくでしょうか。エラー文を Google 検索して原因を推測するでしょうか。しかし、ピンポイントに表示されない大量のエラーといくらにらめっこしていても、エラーの原因を特定できないことが少なくありません。

本記事では、最小のコード再現例を作成することでエラーの原因を特定する方法を紹介します。これによって、エラーの原因となる部分に集中でき、結果的にエラーの解決を早めることが出来ます。また、これを利用することで、エラーの検索の際の目的明確化や質問サイトへの投稿作成を助けます。

以下では、最小の再現コード例を “***MWE***: Minimal Working Example” [^mwe] と呼びます。

[^mwe]: LaTeX では MWE と呼ばれることが多いようです。他にも、このような最小の再現コード例は以下のように呼ばれます。 <sup>[⧉][mre-wiki]</sup>
    - MRE, minimal repro: Minimal Reproducible Example
    - MCVE: Minimal Complete Varifiable Example
    - SSCCE: Short Self-Contained Correct Example

    いずれも問題・バグを再現・実証できる最小のコード例のことを指しています。

[mre-wiki]: https://en.wikipedia.org/wiki/Minimal_reproducible_example "Minimal Reproducible Example - Wikipedia"

:::note info
「パスが通っていないことによるエラー」や「エディタの構成によるエラー」に関しては考慮しないことに注意してください。
:::

[lipsum]: https://www.ctan.org/pkg/lipsum "lipsum - CTAN"
[bxjalipsum]: https://www.ctan.org/pkg/bxjalipsum "bxjalipsum - CTAN"
[mwe]: https://www.ctan.org/pkg/mwe "mwe - CTAN"
[docmute]: https://www.ctan.org/pkg/docmute "docmute - CTAN"
[subfiles]: https://www.ctan.org/pkg/subfiles "subfiles - CTAN"
[standalone]: https://www.ctan.org/pkg/standalone "standalone - CTAN"
[chktex]: https://www.ctan.org/pkg/chktex "chktex - CTAN"
[lacheck]: https://www.ctan.org/pkg/lacheck "lacheck - CTAN"
[filecontents]: https://www.ctan.org/pkg/filecontents "filecontents - CTAN"
[comment]: https://www.ctan.org/pkg/comment "comment - CTAN"

## ■ MWE 作成の意義

MWE を作成する意義は、次の点が挙げられます。

- エラーのある部分と無い部分を分離できる
- エラーの原因を 1 つ 1 つに分割できる
- 元の大きなファイルよりも軽量でテストしやすい
- 同じ環境であれば誰でも問題を再現できるため、問題を誰かと共有して解決策を模索できる
- 外部に出せない文章であっても、共有できるものに改変できる

MWE の 1 つの目的は “分割” です。「困難は分割せよ [^ruroi]」とはよく言ったもので、エラーを分割し小さなものに作り変えることで、原因の特定とエラーの解消に繋げるための第一歩となります。この方法は、一般的に “**分割統治法** (*divide-and-conquer method*)” <sup>[⧉][wiki-divideconquer]</sup> と呼ばれます。

[wiki-divideconquer]: https://www.wikiwand.com/ja/%E5%88%86%E5%89%B2%E7%B5%B1%E6%B2%BB%E6%B3%95 "分割統治法 - Wikiwand"

[^ruroi]: 「仕事がうまくいかないときは、この言葉を思い出してください。『困難は、分割せよ。』あせってはなりません。問題を細かく割って、一つ一つ地道に片づけていくのです。ルロイのこの言葉を忘れないでください。」――― 井上ひさし「握手」より。

当然ですが、エラー原因は別個に分割されるため、MWE は複数作成される場合もあります。1 つ 1 つ解決していきましょう。

また、MWE は MWE 自身が持つ問題が再現され、解決された暁には期待した結果が得られることを意味しています。そのため、MWE はコードとしてタイプセットが実行されるために TeX ファイルとして完全である必要があります。

## ■ LaTeX における MWE のつくりかた

LaTeX における MWE とは「**指定したタイプセット方法で実行すると、特定の問題が再現される最小のコード例**」です。そのため、LaTeX における MWE は通常の再現最小コード例に +*α* タイプセット方法が必要になります。すなわち、LaTeX における MWE は以下の 2 つです。

- 特定の問題が再現される最小のコード例
- タイプセット方法

LaTeX における MWE に +*α* としてタイプセット方法が必要な理由は、タイプセット方法に依っていくつかの細かな違いがあるためです。他のプログラミング言語では、このようなタイプセットによる違いは無いようなので、LaTeX 特有だと思われます。（多くの言語はコンパイラ・インタプリタのバージョンに依存するくらいでしょう）

:::note info
以下では、単に MWE と称した場合、特定の問題が再現される最小のコード例を指すこととし、LaTeX における MWE と称した場合は、MWE にタイプセット方法を加えたものを意味することとします。
:::

次項でそれぞれについて解説します。

### ▽ タイプセット方法

LaTeX におけるタイプセットには複数の方法があります。特に、日本語を組版する場合は代表的に 4 つの方法があります。
- LuaLaTeX
- upLaTeX＋dvipdfmx
- pLaTeX＋dvipdfmx
- XeLaTeX

いずれも LaTeX ですが、それぞれ異なる特徴があります。そのため、生じたエラーがタイプセット方法に由来する場合、これが明らかでないと原因が特定できない可能性があります。

通常はタイプセット方法について常に明らかですが、利用しているタイプセット方法が分からない場合、次の記事を参照してください。

https://qiita.com/zr_tex8r/items/a924be192ecea7e6bbe4

:::note warn
本来は、ターミナルに入力するコマンドとオプション引数を明らかにするべきです。しかし、LaTeX を扱う人にとってこれがハードルの高い要件になることがあるため、この点は割愛しておきます。
:::

### ▽ 特定の問題が再現される最小のコード例

“特定の問題が再現される最小のコード例” は 2 つの部分に分けられます。

- 問題の部分のみを取り出したコード
- なるべく小さくしたプリアンブル

特定の問題が再現される最小のコード例の作成は、次のような手順を踏みます。

1. AUX ファイル等の中間ファイルを削除して、元のファイルを再度一度タイプセットする
    - 中間ファイルによるエラーの可能性を潰す
    - これによって解消される場合があります
1. 外部に移設したファイルをなるべく 1 つのファイルに置き替える
1. エラー原因を二分探索的に特定する
    - プリアンブルを変更しない
    - これが “問題の部分のみを取り出したコード” に相当する
    - 具体的な特定方法については次節
1. エラー原因と関係の無い独自定義コマンド・環境等やパッケージの削除
1. 文書クラスを標準クラスに変更

ここで作成された MWE は元のファイルとは別のファイルとして作成しましょう。元のファイルの下位ディレクトリに作成するなどして管理すると簡便でしょう。

以下では、この手順についてより詳細に確認しましょう。

#### ● エラー原因の二分探索的な特定方法

“二分探索” とは、「ソート済み配列に対する探索アルゴリズムの 1 つ <sup>[Wikipedia][bs-wiki]</sup>」です。

[bs-wiki]: https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%8E%A2%E7%B4%A2 "二分探索 - Wikipedia"

:::note info
ここで言及したい “エラー原因の二分探索的な特定方法” とは、「**コードを半分ずつコメントアウトしながら、エラー発生箇所を絞って当たりを付ける方法**」を指します。

この方法の “肝” は「**常に同じエラーを発行させながらコードを小さくする**」ことにあります。エラーが発行されない部分を削いで、エラーが発行される部分だけを抽出する作業です。
:::

具体的な手順は以下の通りです。

1. MWE 用に別ファイルに転記する
1. document 環境内またはエラーが発行されている環境内において、意味のある単位で 2 分割する
1. 分割した一方をコメントアウトする
1. タイプセットして、エラーが発行されるか確認する
    - <ins> エラーが発行されない場合 </ins>
        - ここにエラーの原因はありません
        5. コメントアウトされた部分を意味のある単位で 2 分割する
        5. 分割した一方のコメントアウトを解除する
        5. *4.* に戻る
    - <ins> エラーが発行された場合 </ins>
        - ここにエラーの原因があります
        5. コメントアウトされていない部分を意味のある単位で 2 分割する
        5. 分割した一方をコメントアウトする
        5. *4.* に戻る
    - <ins> 一部のエラーが発行された場合 </ins>
        - エラーの原因が複数あり、その 1 つの原因がここにあります
        5. エラーの原因と考えられる部分をプリアンブルとともに抜き出して、別のファイルに移動させる
        5. 抜き出した部分をコメントアウトする
        5. *4.* に戻る
1. コードがこれ以上分割できなくなったら終了

これによって、エラーの原因となる部分が絞られます。これが MWE の “問題の部分のみを取り出したコード” に相当します。

複数のエラーが発行されている場合、初めに発見されたエラーのみが全てではない可能性があります。これは注意が必要になります。

もしも、2 分割するにはあまりにも大規模な場合、`\end{document}` を動かす方法があります。LaTeX は `\end{document}` までしか読まないため、これを利用してコメントアウトと同様の操作が可能です。

ブロック単位でコメントアウトを行う [comment][] パッケージは有名ですが、利用することはあまりオススメしません。これは、comment パッケージを利用することで別のエラーが生じる可能性があるためです。

以降では、MWE で示す特定のエラーを **MWE エラー**と呼びます。

:::note warn
独自に定義したコマンド・環境がエラーの原因となっていた場合、複数の場所で同一エラーが発行される可能性があります。

二分探索的な特定方法では、このようなエラー原因は上手く処理できずに、同一複数の MWE を作成することになってしまいます。これを避けるには、早い段階で作成される MWE の傾向を見極める必要があります。
:::

#### ● プリアンブルを小さくする

LaTeX における MWE には、プリアンブル全体が必要です。具体的には、次のようなコマンドすべてを記述せよと言うことです。

- `\documentclass`
- `\usepackage` とそのオプション設定
- `\newcommand` などの独自に定義したコマンド

エラー原因を特定した後、プリアンブルをより小さくして、エラー原因をより深く突き止めます。プリアンブルをより小さくするには、大きく 3 つの手順があります。

1. 不要な独自に定義したコマンド・環境等を削除
    - 関係の無い定義は混乱を招きます
    - これに関しては状況が個々に依るため、詳細な方策は省略します
    - 場合によっては、定義がエラーの原因の可能性もあります [^newcommand]
1. 不要なパッケージを削除
    - パッケージ間の衝突の可能性を考慮できます
1. 文書クラスを標準クラス（`artcle`、`report`、`book`、j(s)classes、ltjsclasses 等）に変更

[^newcommand]: 独自定義コマンド・環境の 2 次的な定義はなるべく避けましょう。これは、定義の複雑化は問題の特定を困難にする可能性があるためです。

第 2・3 について、文書クラス・パッケージについてある程度理解していれば、ざっくりとした変更・削除が可能ですが、次のような手順によってでもプリアンブルを小さくできます。もしも、`\documentclass`・`\usepackage` をオマジナイのように理解している場合であっても、手順に従えば簡単です。

パッケージについて、以下のように小さくします。

1. `\usepackage` をすべてコメントアウト
    - `\usepackage` をコメントアウトした際には、パッケージのオプションになるコマンドもセットでコメントアウトする
1. タイプセットしてエラーを確認する
    - <ins> MWE エラーと異なるエラー状況になった場合 </ins>
        - 削除してはいけないパッケージをコメントアウトしています
        3. コメントアウトされた `\usepackage` の 1 つをコメントアウト解除
        1. *2.* に戻る
    - <ins> MWE エラーと同じエラー状況になった場合 </ins>
        - 不要なパッケージはすべてコメントアウトされています
        - この状態が過不足の無いパッケージです

文書クラスについて、以下のように変更します。

1. 利用している文書クラスを標準クラスに変更する
1. タイプセットしてエラーを確認する
    - <ins> MWE エラーと異なるエラー状況になった場合 </ins>
        - 文書クラスのコマンド・環境に依存した記述があるようです
        - 元の文書クラスに戻しましょう
    - <ins> MWE エラーと同じエラー状況になった場合 </ins>
        - この文書クラスで問題ないようです

標準文書クラスはタイプセット方法に依って異なります。`article`、`report`、`book` はいずれのタイプセットにも対応しますが、j(s)classes、ltjsclasses は特定のタイプセット方法にしか対応しません。また、BXjscls はタイプセット方法に対して独自の指定方法があります。この辺りには少し注意が必要です。

| タイプセット方法 | 文書クラス  |
| :--------------: | :---------: |
|      pLaTeX      |  jclasses   |
|     upLaTeX      |  jsclasses  |
|     LuaLaTeX     | ltjsclasses |

### ▽ 二分探索的な特定方法と MWE 作成の例

次のような文書を書いたとします。Maxwell 方程式を書きました。このファイルにはエラーが含まれています。一見すると、どこにエラーが含まれているか分かりませんね。

```latex
% sample.tex
\documentclass{jlreq}
\usepackage[left=25mm,right=25mm,top=30mm,bottom=30mm]{geometry}
\usepackage{amsmath}
\usepackage{hyperref}
\newcommand{\vect}[1]{\boldsymbol{#1}}
\begin{document}

This is Maxwell's equations.

\begin{align}
  \nabla \cdot \vect{E} (t, \vect{r})
    & = \frac{\rho (t, \vect{r})}{\varepsilon_0}
  \\
  \nabla \times \vect{E} (t, \vect{r})
    & = - \frac{\partial \vect{B} (t, \vect{r})}{\parial t}
  \\
  \nabla \cdot \vect{B} (t, \vect{r})
    & = 0
  \\
  \nabla \times \vect{B} (t, \vect{r})
    & = \mu_0 \vect{i} (t, \vect{r}) + \varepsilon_0 \mu_0 \frac{\partial \vect{E} (t, \vect{r})}{\partial t}
\end{align}

\end{document}
```

このファイルを以下のターミナルで実行します。

```console
$ lualatex -interaction=nonstopmode -file-line-error sample.tex
```

すると、次のようなエラーログが表示されます。このログを見ると、`./sample.tex:23:` があります。これは、「<samp>sample.tex</samp> の 23 行目でエラーがある」ことを意味しています。

```log
./sample.tex:23: Undefined control sequence.
<argument> \parial
        t
l.23 \end{align}
```

23 行目は `\end{align}` であり、これ自体は問題ありません。LaTeX は、環境内のエラーは環境の終わり `\end{...}` にエラーがあるようなログを発行します。すなわち、align 環境内に原因があるものの、どこが原因かは具体的に分からない状況です。

この例では単純なタイポによるエラーなので、ある程度慣れていれば解決方法はすぐに思い当たると思いますが、今回は二分探索的にエラー原因を探してみます。

----------

<samp>sample.tex</samp> を <samp>sample-temp.tex</samp> に転記して、別ファイルとして二分探索的な特定方法を開始します。

エラー文から、align 環境内に原因があることは明らかなので、まずは align 環境の外にある「This is Maxwell's equations.」は消してしまいましょう。次に、二分探索的に 4 つの式の内の前半 2 式をコメントアウトしてみましょう。

```latex
% sample-temp.tex
\documentclass{jlreq}
\usepackage[left=25mm,right=25mm,top=30mm,bottom=30mm]{geometry}
\usepackage{amsmath}
\usepackage{hyperref}
\newcommand{\vect}[1]{\boldsymbol{#1}}
\begin{document}

\begin{align}
  % \nabla \cdot \vect{E} (t, \vect{r})
  %   & = \frac{\rho (t, \vect{r})}{\varepsilon_0}
  % \\
  % \nabla \times \vect{E} (t, \vect{r})
  %   & = - \frac{\partial \vect{B} (t, \vect{r})}{\parial t}
  % \\
  \nabla \cdot \vect{B} (t, \vect{r})
    & = 0
  \\
  \nabla \times \vect{B} (t, \vect{r})
    & = \mu_0 \vect{i} (t, \vect{r}) + \varepsilon_0 \mu_0 \frac{\partial \vect{E} (t, \vect{r})}{\partial t}
\end{align}

\end{document}
```

これを先ほどと同様にタイプセットすると、エラー無く終了します。したがって、ここにはエラーとなる原因は無いことが分かります。

:::note warn
より大規模な二分探索的な特定する場合は、エラーの原因の有無をどこまで確認したか分かるように、以下のような目印を適当に付けておいてください。

```latex
% ↓ ここまではエラーなし
```

目印が無い場合、どこまで確認したか分からなくなってしまうことがあります。
:::

次に、コメントアウトした 2 式の内の 1 つをコメントアウトから解除しましょう。

```latex
% sample-temp.tex
\documentclass{jlreq}
\usepackage[left=25mm,right=25mm,top=30mm,bottom=30mm]{geometry}
\usepackage{amsmath}
\usepackage{hyperref}
\newcommand{\vect}[1]{\boldsymbol{#1}}
\begin{document}

\begin{align}
  % \nabla \cdot \vect{E} (t, \vect{r})
  %   & = \frac{\rho (t, \vect{r})}{\varepsilon_0}
  % \\
  \nabla \times \vect{E} (t, \vect{r})
    & = - \frac{\partial \vect{B} (t, \vect{r})}{\parial t}
  \\
  \nabla \cdot \vect{B} (t, \vect{r})
    & = 0
  \\
  \nabla \times \vect{B} (t, \vect{r})
    & = \mu_0 \vect{i} (t, \vect{r}) + \varepsilon_0 \mu_0 \frac{\partial \vect{E} (t, \vect{r})}{\partial t}
\end{align}

\end{document}
```

これも先ほどと同様にタイプセットしてみます。すると、初めと同じエラーが発行されました。これすなわち、いまコメントアウトを解除した 13\~15 行目に原因があると言うことです。

:::note warn
いまコメントアウトされている 8\~10 行目にエラーの原因が無いことは示していないことに注意してください。次の作業によって、8\~10 行のエラーの有無が確認されます。

1. 10\~12 行目のコメントアウトを解除
1. エラーのある 13\~15 行目をコメントアウト
1. タイプセット

もしも、10\~12 行目でもエラーが生じた場合、別個の MWE として作成してください。
:::

問題となっている箇所を取り出してよく見てみると、右辺分母の `\partial` の `t` が抜けています！（エラー文の “Undefined control sequence.” では、「未定義のコマンドがある」⇒「タイポの可能性」を示唆していました）

```latex
  \nabla \times \vect{E} (t, \vect{r})
    & = - \frac{\partial \vect{B} (t, \vect{r})}{\parial t}
                                                  % ↑
  \\
```

今回はエラーの原因を特定・解決することが出来ましたが、いつも解決できるとは限りません。すぐに解決方法が分からない場合は MWE を作成します。

これまでにエラーの原因となっている箇所は特定し抜き出しているため、次にプリアンブルをより小さくすることを考えましょう。現在のプリアンブルは以下のようになっていました。

```latex
\documentclass{jlreq}
\usepackage[left=25mm,right=25mm,top=30mm,bottom=30mm]{geometry}
\usepackage{amsmath}
\usepackage{hyperref}
\newcommand{\vect}[1]{\boldsymbol{#1}}
```

今回のエラー原因は数式に関するものであることが類推されるため、パッケージは amsmath 以外削除し、文書クラスは jlreq から article に変更してみましょう。

```latex
% sample-mwe.tex
\documentclass{article}
\usepackage{amsmath}
\newcommand{\vect}[1]{\boldsymbol{#1}}
\begin{document}

\begin{align}
  \nabla \times \vect{E} (t, \vect{r})
    & = - \frac{\partial \vect{B} (t, \vect{r})}{\parial t}
  \\
\end{align}

\end{document}
```

これをタイプセットすると同じエラーが再現されるため、これが今回作成されるべき MWE になります。（実際は、もっとコードを少し小さくして `\parial` が原因であることを突き止めることが出来ます）

当然ですが、プリアンブルをこれ以上小さくすると、異なるエラーが発行されるようになります。

簡単な例しか示していませんが、多くの場合であっても同じような方策で MWE を作成できます。複雑なコードだった場合、この例よりもより強力な効果を発揮します。

----------

もしも、この MWE を共有して質問する場合、希望する完成形を見せることも大事になります。今回は数式なので、手書きの数式を見せるなどして完成形を共有すると良いでしょう。完成形が上手く共有されない場合、誤った方向にリードされてしまう可能性があります。

## ■ 問題を特定しやすいファイル構成

ファイルは大きくなればなるほどエラー原因を特定することが難しくなります。特定を容易にするためには、ファイルを分割することです。

ファイル分割には、次のような方法があります。（本記事では、これらの方法の詳細について紹介しません）

- デフォルトの `\input`、`\include`
- [docmute][] パッケージ
- [subfiles][] パッケージ
- [standalone][] パッケージ

ただし、デフォルトの `\input`・`\include` は問題を特定しづらい場合があります。これは、サブファイルが独立してタイプセット出来ないためです。出来る限り、documute や subfiles パッケージ等を利用することをオススメします。

また、意味の切れるところで改行することをオススメします。これは、二分探索的なエラー原因の特定で役立ちます。1 行にあまりにも多くの情報があると、コメントアウトしづらくなってしまいます。なるべく改行出来るところで改行しましょう。

適切な改行・適切なインデントは、ファイルをより読みやすいものにします。目に優しいファイルを作成すれば、構文エラーも発見しやすいものになります。LaTeX でも readable なコードを書くべきです。

## ■ 質問サイトに投稿するときの注意点

Google 検索や LaTeX 美文書などの書籍を読んでもエラーを解消することが出来なかった場合、質問サイトで解決方法を質問することを検討します。この節では、質問サイトに投稿するときに書き込むべき事項や注意点を挙げたいと思います。

[TeX Forum][texforum] や [teratail][]、[Stack][stackoverflow-en] [Overflow][stackoverflow-ja] で質問する際には、質問者の人物像的な情報も必要ですが、LaTeX に関する情報は少なくとも以下の 6 点について明らかにする必要があります。[^ugly]

[texforum]: https://okumuralab.org/tex/ "TeX Forum"
[teratail]: https://teratail.com/tags/LaTeX "LaTeX - teratail"
[stackoverflow-ja]: https://ja.stackoverflow.com/questions/tagged/latex "LaTeX - スタック・オーバーフロー"
[stackoverflow-en]: https://tex.stackexchange.com/ "TeX - LaTeX Stack Exchange"

[^ugly]: もちろん、常にこれらの情報がすべて揃っている必要はありません。しかし、今回考えているエラーは、質問者が解決方法を知らないことを前提としています。そのため、これら 6 つの情報の中に不要な情報があるかどうかも判別が付かないものとしています。

- **MWE**
- **タイプセット方法**：
    - *e.g.* LuaLaTeX、upLaTeX＋dvipdfmx etc.
    - BibTeX やその他のツールを利用していれば、これらも明記する必要がある
- **MWE をタイプセットしたときの LOG ファイル**：
    - LOG ファイルのエラー情報は解決の手掛かりになる
    - 可能であれば MWE エラーのみを抽出しても良い
- **どのような結果を得たいのか**：
    - ゴールは明確に。質問タイトルにも対応する
    - 回答者のミスリードを未然に防ぐ
- **TeX ディストリビューション**：*e.g.* TeX Live 20XX、MacTeX etc.
    - 場合によっては、利用している文書クラス・パッケージのバージョン情報 (`\listfiles`)
- **OS**：*e.g.* Windows 1X、macOS v1X、Linux etc.

これに加えて、エラー解消のために試したことも列挙しておくと良いです。少なくとも「“答え” だけ欲しくて訊きに来た」という印象を無くすことが出来ます。また、出力された結果が期待したものとは異なる場合、出力された結果のスクリーンショットがあっても良いでしょう。解決への手助けになる可能性があります。

これ以外にも、明らかに質問者にしか分からないような事柄は必ず含めるべきです。もしも情報が不足している場合、回答者の一言目は「〜について教えてください」になってしまいます。これでは質疑応答が 1 往復無駄になってしまい、解決まで時間がかかってしまします。過不足の無い情報を出し惜しみせずに開示しましょう。

海千山千な LaTeX の達人や仙人は、情報が欠けていても数多くの経験に裏打ちされた類い稀な <ruby> 特殊能力 <rp>(</rp><rt> エスパー </rt><rp>)</rp></ruby> によって解決への糸口を見つけることがあります。しかし、回答者の門戸をより広く持つためには、これらを網羅している必要があるでしょう。

質問の書き方について、次項も注意すると良いでしょう。

- 1 つの質問には 1 つの MWE
- 情報は出来るだけテキストで投稿する
    - スクリーンショットでは読みづらい
    - 逆に、希望する完成形は図示すると分かりやすい
    - ファイル添付できる場合は、ZIP ファイル等として投稿すると手堅い
- MWE や LOG ファイルはコードブロック内に入れる
    - Markdown が有効の場合は ` ``` ` で囲えば良い
    - 言語指定する場合は、開きを ` ```latex ` とする
- LaTeX の環境構築過程の説明で「〜の記事を参考にして……」だけではなく、実際に利用している環境や設定をきちんと書く

このような注意点は TeX Wiki にも記載があります。

https://texwiki.texjp.org/?%E8%B3%AA%E5%95%8F%E3%81%AE%E3%81%97%E3%81%8B%E3%81%9F

### ▽ バージョン情報の確認方法

TeX ディストリビューションのバージョン情報は、以下のようにすると調べることが出来ます。

```console
$ tex --version
TeX 3.141592653 (TeX Live 2023)
kpathsea version 6.3.5
Copyright 2023 D.E. Knuth.
There is NO warranty.  Redistribution of this software is
covered by the terms of both the TeX copyright and
the Lesser GNU General Public License.
For more information about these matters, see the file
named COPYING and the TeX source.
Primary author of TeX: D.E. Knuth.
```

----------

文書クラス・パッケージのバージョンによってエラーが生じている場合があります。そのため、現在使っている TeX ディストリビューションに導入されている文書クラス・パッケージのバージョンを知る必要があります。

`\listfiles` をファイルのプリアンブル内に書き込むことで、LOG ファイルに文書クラス・パッケージのバージョンが記載されます。

先のコード例で作成された <samp>sample-mwe.tex</samp> に `\listfiles` を挿入してタイプセットすると、次のようなログが追加されます。

<details>
<summary>MWE とターミナル（折りたたみ）</summary>

```latex
% sample-mwe.tex
\documentclass{article}
\usepackage{amsmath}
\newcommand{\vect}[1]{\boldsymbol{#1}}
\listfiles
\begin{document}

\begin{align}
  \nabla \times \vect{E} (t, \vect{r})
    & = - \frac{\partial \vect{B} (t, \vect{r})}{\parial t}
  \\
\end{align}

\end{document}
```

```console
$ lualatex -interaction=nonstopmode -file-line-error sample-mwe.tex
```

</details>

```log
 *File List*
 article.cls    2022/07/02 v1.4n Standard LaTeX document class
  size10.clo    2022/07/02 v1.4n Standard LaTeX file (size option)
 amsmath.sty    2022/04/08 v2.17n AMS math features
 amstext.sty    2021/08/26 v2.01 AMS text
  amsgen.sty    1999/11/30 v2.0 generic functions
  amsbsy.sty    1999/11/29 v1.2d Bold Symbols
  amsopn.sty    2022/04/08 v2.04 operator names
l3backend-luatex.def    2023-03-30 L3 backend support: PDF output (LuaTeX)
  ts1cmr.fd    2022/07/10 v2.5l Standard LaTeX font definitions
 ***********
```

質問サイトに投稿する場合、多くは TeX ディストリビューションのバージョンのみで問題ないと思われますが、文書クラス・パッケージのバージョンを求められた際には出せるようにしておくと良いでしょう。

用意周到にしておこうと思えば、質問サイトで利用する MWE には原則的に `\listfiles` を与えておき、LOG ファイルにバージョン情報が記載されているようにしておいても良いでしょう。

### ▽ ダミーテキスト・画像

外部に出せない文章や画像の場合は、ダミーを利用すると良いでしょう。これは、もちろんテキトーに文章を打ったり図を挿入したりすれば良いのですが、これをパッケージからサポートすることが出来ます。

- ダミーテキスト
    - [lipsum][] パッケージ（英語用）
    - [bxjalipsum][] パッケージ（日本語用）
- ダミー画像
    - `\rule{<width>}{<height>}`
    - [mwe][] パッケージ

ただし、これらのダミーに変更した際に、元の MWE エラーと異なるエラーが発行されていないことを確認してください。

### ▽ filecontents 環境

BiB ファイル等 TeX ファイル以外のファイルを含んで、TeX ファイル 1 つとして表現したい場合、filecontents 環境を利用します。

```latex
\begin{filecontents}{filename.bib}
% ここに BiB ファイルの内容を書く
\end{filecontents}
\documentclass{article}
% プリアンブル
% ...
\begin{document}
% ...
\end{document}
```

日本語による filecontents 環境を解説はあまり見つからないため、次の Unofficial LaTeX2e reference manual を参照してください。[^filecontents]

[^filecontents]: 実際に利用する場合、この filecontents 環境には以下 2 点の制限があります。
    - プリアンブルでしか構成できない
    - filecontents 環境を編集しても出力されたファイルを上書きしない

    この問題は [filecontents][] パッケージを利用すると解消されます。

http://latexref.xyz/filecontents.html

Stack Overflow ではしばしば見かけることになりますが、別ファイルを 1 つのファイルとして表現しているだけです。怖がる必要はありません。

これは、質問する際に filecontents 環境を利用しなければならないと言うことではありません。もしも複数のファイルがあっても複数のファイルがあることを示していれば問題ないでしょう。

### ▽ ディレクトリ構造の表現

[\# この節][sec-filestrc] でファイルを分割することを紹介していますが、MWE が複数のファイルで構成される場合、質問する際にディレクトリ構造を明記する必要になる場合があります。

[sec-filestrc]: #-問題を特定しやすいファイル構成 "§ 問題を特定しやすいファイル構成"

ディレクトリ構造は、次のようなコードブロックで表現します。

- ASCII
    ```
    .
    |- main.tex
    |- chp1/
    |   |- sec1.tex
    |   `- sec2.tex
    `- img/
        `- dog.pdf
    ```
- Unicode
    ```
    .
    ├─ main.tex
    ├─ chp1/
    │   ├─ sec1.tex
    │   └─ sec2.tex
    └─ img/
        └─ dog.pdf
    ```

状況によってディレクトリ構造は異なるため、その都度自力で書く必要がありますが、ある程度書ける能力があると良いです。

# 参考

- [質問のしかた - TeX Wiki](https://texwiki.texjp.org/?%E8%B3%AA%E5%95%8F%E3%81%AE%E3%81%97%E3%81%8B%E3%81%9F)
- [Hilfe für LaTeX-Einsteiger](https://minimalbeispiel.de/)
    - [What is a minimal working example?](https://minimalbeispiel.de/mini-en.html)
- [再現可能な短いサンプルコードの書き方 - ヘルプセンター - スタック・オーバーフロー](https://ja.stackoverflow.com/help/minimal-reproducible-example)
- [エラーメッセージの読み方と対処, 検索や質問の原則 - Qiita](https://qiita.com/cannorin/items/eb062aae88bfe2ad6fe5)

# 余談

LaTeX は文章作成のためのマークアップ言語でありながら、多分にプログラミング言語要素を含んでいます。LaTeX は他のプログラミング言語を触ったことのない人でも利用することがあり、これらの人にとってエラーの解消方法は難しいものになりがちです。

今回、MWE を書いてエラー原因を特定するような LaTeX 向けのアプローチ記事が無かったので書きました。是非とも、エラーが生じた際には MWE を作成してみてほしいです。

記事を書いていて、LaTeX のエラー解消方法についてむしろ少しハードルを上げたような気もしますが、MWE の作成は慣れれば作業なので簡単です。私はやってないですが、自身が遭遇したエラーと解決した MWE を実例集として集積しておけば、未来の自分に多くの投資ができる可能性があります。