Missing $ inserted

! Missing $ inserted est l’erreur la plus fréquente de LaTeX, et le texte d’aide qui la suit se termine par les mots Proceed, with fingers crossed (« on continue, en croisant les doigts »). Cette formule est de Donald Knuth, inscrite dans TeX lui-même dans les années 1980, et elle s’affiche encore chaque jour sur un écran quelque part. Le message ne veut dire qu’une chose : quelque chose qui n’est valable qu’en mathématiques est apparu dans du texte ordinaire. Le coupable est en général un tiret bas _ voulu au sens littéral, un exposant ^, un \alpha égaré, ou un $ bien plus haut qui n’a jamais été refermé. Cette page explique comment lire le message, pourquoi le numéro de ligne annoncé se situe souvent après la faute, et quoi écrire aux trois endroits où la réponse diffère : le texte courant, \verb et \url.

De quoi se plaint réellement ! Missing $ inserted

Elle signifie qu’un token qui n’existe qu’en mode mathématique est arrivé alors que TeX composait du texte horizontal ordinaire — rien de plus. TeX suppose un début de mathématiques oublié, insère discrètement un $ et poursuit. La correction tient en une phrase : si vous vouliez des mathématiques, encadrez ($x_1$) ; si vous vouliez le caractère lui-même, échappez-le (\_). Un cran plus bas, le mécanisme est celui des codes de catégorie. TeX attribue un numéro à chaque caractère d’entrée : _ a le catcode 8 (indice), ^ le 7 (exposant), $ le 3 (bascule mathématique). Or les catcodes 7 et 8 ne sont légaux qu’à l’intérieur des mathématiques. \alpha et \frac échouent pour la même raison : en interne, ils réclament des caractères de classe mathématique.

latex
% "$" is not sacred: it is just the character whose catcode is 3.
% Give catcode 3 to "!" and it opens and closes math exactly like $.
\catcode`\!=3
Then !x_1! typesets as math.   % compiles with zero errors

L’extrait ci-dessus a l’air d’une plaisanterie, mais il compile sans la moindre erreur sous TeX Live 2024. $ n’a rien de sacré : c’est simplement le caractère dont le catcode vaut 3. Une fois cela admis, l’erreur cesse d’être mystérieuse : il s’agit d’une confusion sur le rôle d’un caractère. Il en découle aussi que _ et ^ ne sont pas les seuls caractères spéciaux à mal se comporter dans le texte — mais un caractère différent donne une erreur différente, d’où le tableau ci-dessous pour situer votre symptôme. Idée fausse très répandue : écrire & dans du texte ordinaire ne produit pas ! Missing $ inserted.

CaractèreCatcodeCe qui se passe dans le texte courant
_8! Missing $ inserted. Pour un vrai tiret bas, écrire \_
^7! Missing $ inserted. Le signe littéral est \textasciicircum
$3Ouvre/ferme les mathématiques. Isolé, il laisse les maths ouvertes jusqu’à la fin du paragraphe
&4Autre erreur : ! Misplaced alignment tab character &. Signe littéral : \&
%14Aucune erreur. Il avale la fin de la ligne, y compris un $ fermant
#6! You can’t use ‘macro parameter character #’ in horizontal mode
~13Aucune erreur ; devient une espace insécable (signe littéral : \textasciitilde)

Comment lire <inserted text> et la ligne l.3

Le $ affiché sous <inserted text> a été ajouté par TeX lui-même ; il ne figure pas dans votre fichier. La ligne l.3, elle, est la scène de crime : TeX imprime la ligne fautive coupée en deux, et la coupure indique exactement jusqu’où il avait lu. Voici la sortie réelle de pdfLaTeX (TeX Live 2024) pour un fichier de quatre lignes dont le corps se réduit à The value x_1 is here. La coupure tombe juste après x_ : TeX s’est arrêté à l’instant où il a lu le tiret bas. Cet affichage en deux parties est ce qu’un rapport d’erreur TeX a de plus utile, car il localise précisément la position dans une longue ligne.

log
! Missing $ inserted.
<inserted text>
                $
l.3 The value x_
                1 is here.
I've inserted a begin-math/end-math symbol since I think
you left one out. Proceed, with fingers crossed.

Le même message, mot pour mot, sort aussi de plain TeX. Ce n’est donc pas un message de LaTeX mais un message du moteur TeX lui-même, et il apparaît même sans la moindre ligne \usepackage dans le fichier. C’est pourquoi, en cherchant la cause, il faut soupçonner ce qu’on a tapé avant de soupçonner un package. La dernière phrase du texte d’aide, Proceed, with fingers crossed, est pour l’essentiel inchangée depuis le gel de TeX en 1990.

Pourquoi le numéro de ligne annoncé se situe après la faute

TeX signale la ligne où il s’en est aperçu, pas celle où la faute a été commise. Pour ce qui est illégal dès la lecture, comme _, les deux coïncident. Mais pour les fautes qui laissent les mathématiques ouvertes — un $ jamais refermé —, TeX ne s’en aperçoit qu’à la fin du paragraphe, c’est-à-dire à la prochaine ligne vide. Puisqu’une formule ne peut pas franchir un changement de paragraphe, la ligne vide est le premier moment où TeX peut conclure que les mathématiques sont restées ouvertes. Dans le fichier ci-dessous, la faute est à la ligne 3, mais l’erreur est signalée à la ligne 4, la ligne vide.

document.tex
\documentclass{article}
\begin{document}
The rate is $x% of the total$ per year.

Next paragraph.
\end{document}
log
! Missing $ inserted.
<inserted text>
                $
l.4

I've inserted a begin-math/end-math symbol since I think
you left one out. Proceed, with fingers crossed.

Le piège est le % de la ligne 3. Un signe pour-cent non échappé met en commentaire la fin de la ligne — y compris le $ fermant —, si bien que les mathématiques restent ouvertes jusqu’à la ligne suivante. Rien n’apparaît à droite de l.4 parce que la ligne 4 est la ligne vide. Quand la ligne d’erreur est vide, lisez : « les mathématiques sont ouvertes depuis un point plus haut ». En pratique, le plus rapide est de remonter au paragraphe qui précède immédiatement la ligne signalée et d’y compter les $. Les éditeurs apparient les accolades, pas les $ ; cette étape vous revient. Par le même mécanisme, une ligne où l’on a tapé 50% au lieu de 50\% produira une erreur incompréhensible plusieurs lignes plus loin.

Imprimer un tiret bas littéral : \_, \textunderscore et _ dans \verb

Si vous voulez seulement un nom de fichier comme data_set.csv, la réponse est data\_set.csv. Mais le rapport entre \_ et \textunderscore mérite un détour. Dans le fichier noyau latex.ltx, \_ est défini comme « \nfss@text{\textunderscore} en mode mathématique, sinon \textunderscore » — c’est la même chose. Dans le texte, les deux sont donc strictement équivalents ; \_ n’est que la forme courte qui fonctionne aussi en mathématiques. Le point suivant compte davantage : avec l’encodage OT1 par défaut, le tiret bas est tracé comme un filet, pas composé comme un caractère. La définition du noyau est \leavevmode \kern.06em\vbox{\hrule\@width.3em}, un filet horizontal de 0,3 em. Résultat : impossible de copier ce tiret bas depuis le PDF, et la recherche dans le PDF ne le trouve pas. Ajoutez \usepackage[T1]{fontenc} et \DeclareTextSymbol{\textunderscore}{T1}{95} de t1enc.def prend le relais, avec un vrai glyphe copiable et cherchable. Passé à pdftotext, le même document donne data set en OT1 et data_set en T1.

Ce qu’on écritRésultatQuand l’utiliser
\__forme standard ; valable en texte et en mathématiques
\textunderscore_ce en quoi \_ se développe ; aucune différence en texte
\verb|a_b|a_bsans échappement ; y écrire \_ imprime aussi la barre oblique
underscore_un package ; une fois chargé, un _ nu devient sûr dans le texte
\textasciicircum^un accent circonflexe littéral, pas un exposant
latex
% math, when you mean math
The value $x_1$ and $\alpha$ are positive, and $x^2 \ge 0$.

% characters, when you mean characters
Open data\_set.csv, then press \textasciicircum{}C to stop.

% verbatim, when the string is code
Run \verb|make data_set^2| in the shell.

Dans \url et siunitx, la réponse s’inverse

N’échappez pas _ à l’intérieur de \url{...}. \url{https://example.com/a_b} passe correctement tel quel, alors que \url{a\_b} imprime a\_b, barre oblique comprise. La raison : le package url réécrit les codes de catégorie avant de lire son argument et rend à _ et à ses congénères leur statut de caractère ordinaire. Même esprit chez siunitx : \num et \qty ouvrent eux-mêmes le mode mathématique, si bien que \qty{2.5}{\micro\metre} s’écrit directement dans le texte courant. Autrement dit, ce qu’il faut taper dépend de l’argument dans lequel on se trouve. La règle empirique est simple : si la commande traite son contenu littéralement, mettez le caractère nu ; sinon, échappez-le. \verb, \url et \lstinline de listings relèvent du premier cas ; \section, \caption et \footnote du second.

latex
\usepackage{url}       % or hyperref, which loads url
\usepackage{siunitx}
...
\url{https://example.com/a_b}    % right: bare underscore
\url{https://example.com/a\_b}   % wrong: prints the backslash
\qty{2.5}{\micro\metre}          % siunitx opens math for you

Une ligne vide dans \[ … \] et ! Display math should end with $$

Une seule ligne vide dans une formule hors texte produit trois erreurs. On coupe une formule sur deux lignes pour la lisibilité, et le document casse. Placez une ligne vide entre \[ E = mc^2 et F = ma : TeX Live 2024 émet successivement ! Missing $ inserted, ! Display math should end with $$ et ! LaTeX Error: Bad math environment delimiter. Toutes trois découlent de la même règle : une formule ne peut pas franchir un changement de paragraphe. Pour couper une formule, utilisez l’environnement align ou \\, jamais une ligne vide ; pour insérer de la prose entre deux lignes d’une formule hors texte, il y a \intertext d’amsmath. Notez que ! Display math should end with $$ apparaît aussi lorsque le nombre de dollars ouvrants et fermants ne concorde pas, comme dans $$ … $. En LaTeX, l’usage est \[ … \] et non $$, car $$ ignore les paramètres d’espacement tels que \abovedisplayskip.

log
! Missing $ inserted.
<inserted text>
                $
l.5

! Display math should end with $$.
<to be read again>
                   \tex_par:D
l.5

! LaTeX Error: Bad math environment delimiter.
l.7 \]

Quand une seule faute donne cinq erreurs

Quand les erreurs affluent, ne corrigez que la première. Les autres sont presque toujours des dégâts collatéraux du $ inséré par TeX. Compilez un fichier dont le corps se réduit à \frac{1}{2} en texte ordinaire et vous obtenez une chaîne de trois : ! Missing $ inserted\frac), ! Extra }, or forgotten $. (venu de l’accolade fermante du \over dans la définition de \frac), puis de nouveau ! Missing $ inserted à \end{document}. Après la première erreur, TeX poursuit toujours en mode mathématique, si bien que le texte suivant est interprété comme des mathématiques : des blancs étranges apparaissent au milieu des mots, l’espacement de la ponctuation se détraque et d’autres erreurs pleuvent. La marche à suivre est donc fixée : corriger la première erreur et recompiler. Lire les messages suivants avant cela est du temps perdu.

  • Aller à la ligne l.N indiquée et la lire jusqu’à la coupure ; le caractère juste après la coupure est le coupable.
  • Si la coupure tombe sur une ligne vide, compter les $ dans le paragraphe précédent : un nombre impair signale un $ non refermé.
  • Relire la même ligne jusqu’au bout : un % non voulu comme commentaire avale-t-il le $ fermant ?
  • Si vous vouliez des mathématiques, écrivez $ … $ ; si vous vouliez des caractères, \_, \%, \&, \#, \textasciicircum{}.
  • Pour montrer du code ou des identifiants tels quels, utilisez \verb ou listings au lieu de raisonner échappement par échappement.
  • Après correction, recompiler avant de lire l’erreur suivante.