Los mensajes de error de LaTeX se leen mal porque no son trazas de pila. Las dos líneas apiladas bajo ! Undefined control sequence no explican qué comando está mal: fotografían el cabezal de lectura de TeX en el instante en que se detuvo — la línea de arriba es lo ya leído, la de abajo lo que aún no lo estaba, y la ruptura entre ambas es el lugar del accidente. Una vez entendido eso, el mismo mecanismo explica por qué el número de línea l.NN a veces miente, si conviene teclear h o x en el prompt ?, y por qué el archivo .log guarda más de lo que el terminal llegó a mostrar. Esta página cubre la anatomía de un error de TeX, -file-line-error, los cuatro modos -interaction, la lectura del registro y cómo acorralar la causa por bisección.
Anatomía de un error de TeX: la línea ! y las dos líneas apiladas
La línea ! dice qué ocurrió; las dos líneas apiladas que empiezan en l.NN dicen dónde se detuvo TeX, y el culpable está casi siempre en el extremo derecho de la línea superior. TeX corta la línea de entrada en lo leído y lo no leído, apila ambas mitades y marca el corte con sangría. En el ejemplo de abajo la mitad superior termina en \textbnf, justo el comando que reventó al ser leído; {bold} text. aún no se había tocado y por eso queda en la mitad inferior. Ese corte es mucho más fiable que el número de línea: el número indica dónde TeX se dio cuenta, el corte indica dónde TeX estaba.
! Undefined control sequence.
l.3 This is \textbnf
{bold} text.
? A veces aparecen líneas adicionales encima de l.NN: son el contexto del error. Una línea con ->, como \mynorm #1->\lVert, indica que el fallo ocurrió dentro de la expansión de esa macro. <inserted text> es un token que TeX añadió por su cuenta para recuperarse, <to be read again> uno que consumió y devolvió a la cola, y <read *> significa que está esperando algo escrito en el terminal. Cuando una línea no cabe en el terminal, su comienzo se elide con ..., así que una presentación como l.9 ...: $\frac{1}{2}$ and a stray \undefinedmacro empieza en realidad más a la izquierda.
| Línea de contexto | Qué señala |
|---|---|
l.NN | la línea de entrada que se leía; el corte entre mitades es el punto de parada |
\mac #1-> | ocurrió dentro de la expansión de \mac; la definición está en otro sitio |
<inserted text> | un token que TeX añadió para recuperarse, a menudo un $ |
<recently read> | el token recién consumido, que suele ser la causa |
<to be read again> | un token consumido y devuelto a la cola; se leerá de nuevo |
<argument> | ocurrió dentro de un argumento: mire el argumento, no la llamada |
<read *> | espera entrada del terminal; un modo no interactivo aborta de inmediato |
Por qué l.NN a veces se pasa exactamente una línea
Un error provocado por \usepackage suele señalarse una línea más tarde de donde ocurrió, y la culpa es del argumento de fecha opcional que \usepackage admite al final. Como \usepackage[opt]{pkg}[2021/02/14] es legal, TeX debe mirar más allá de la llave de cierre para ver si sigue un [; esa anticipación salta espacios y saltos de línea, de modo que ya ha leído la línea siguiente cuando el error se dispara. Medido en TeX Live 2024: con \usepackage[latin1]{inputenc} en la línea 3, el choque de opciones se informa en l.4; añadir un [2021/02/14] explícito al final de esa misma línea lo devuelve a l.3. Así que si un error relacionado con un paquete apunta a una línea vacía o a \begin{document}, mire una línea más arriba.
% \usepackage[latin1]{inputenc} sits on line 3 -- reported at line 4
./oc1.tex:4: LaTeX Error: Option clash for package inputenc.
l.4 \begin
{document}
% same source, but the optional date argument is written out
% -- the look-ahead ends on line 3, and so does the report
./ocA.tex:3: LaTeX Error: Option clash for package inputenc.
l.3 \usepackage[latin1]{inputenc}[2021/02/14]La misma distancia entre «donde TeX se dio cuenta» y «donde está el fallo» se abre con una } sin cerrar, salvo que ahí puede abarcar decenas de líneas en lugar de una, y TeX acaba rindiéndose al final de un párrafo o en \end{document}. Los casos concretos —modo matemático perdido, comandos indefinidos, llaves que faltan— tienen cada uno su página. Lo único que hay que llevarse aquí es la regla general: cuanto más inocente parezca la línea señalada, más arriba está la causa.
-file-line-error: el formato al que el editor sabe saltar
Con -file-line-error, el ! inicial se sustituye por ./file.tex:3:, lo que reúne nombre de archivo y número de línea en una sola línea, de modo que un editor o un analizador de registros de CI puede saltar allí directamente. El formato por omisión tiene una carencia real: l.3 solo da un número, y el nombre del archivo hay que deducirlo de un paréntesis de apertura como (./chapters/intro.tex impreso mucho más arriba. En un documento dividido en capítulos con \input, esa deducción es donde se va el tiempo. -file-line-error la elimina, y las dos líneas apiladas l.NN se siguen imprimiendo, así que no se pierde nada.
$ pdflatex main.tex
(./chapters/intro.tex
! Undefined control sequence.
l.2 Here is \nosuchcmd
in a chapter.
$ pdflatex -file-line-error main.tex
(./chapters/intro.tex
./chapters/intro.tex:2: Undefined control sequence.
l.2 Here is \nosuchcmd
in a chapter.En muchas instalaciones este formato ya viene activado: latexmk lo enciende internamente y entornos como TeXworks o LaTeX Workshop para VS Code lo añaden por su cuenta. Al invocar el motor a mano hay que pasar -file-line-error, o -no-file-line-error para desactivarlo de forma explícita. Un efecto lateral útil: cuando el error procede de un paquete, la ruta mostrada es la del archivo de ese paquete — una línea /usr/local/texlive/…/foo.sty:120: significa que quien protesta es foo, no lo escrito a mano.
El prompt ?: h, i, x, q, r, s y Retorno
Hay nueve respuestas posibles ante un prompt ?, y teclear ? hace que TeX imprima la lista él mismo. Es el comportamiento del errorstopmode predeterminado, en el que TeX pregunta literalmente qué hacer. Tres respuestas concentran casi todo el uso: Retorno (ignorar este error y continuar), h (mostrar el párrafo de ayuda propio de TeX para ese mensaje) y x (abandonar de inmediato, sin producir PDF). Si un documento largo puede contener más errores, lo más rápido es teclear r o s, dejar terminar la compilación y leer luego el .log.
? ?
Type <return> to proceed, S to scroll future error messages,
R to run without stopping, Q to run quietly,
I to insert something, E to edit your file,
1 or ... or 9 to ignore the next 1 to 9 tokens of input,
H for help, X to quit.
?| Respuesta | Qué hace TeX |
|---|---|
Return | olvidar este error y seguir; la composición continúa y se produce el PDF |
h | imprimir el párrafo de ayuda de este mensaje; el .log ya lo contiene |
i | insertar texto en ese punto — i\textbf corrige una errata solo para esta ejecución |
x | abandonar de inmediato; imprime No pages of output. y no escribe PDF |
q | muestra OK, entering \batchmode y termina la compilación en silencio |
r | muestra OK, entering \nonstopmode... y llega al final sin detenerse |
s | muestra OK, entering \scrollmode...; no se detiene, pero sigue leyendo del terminal |
e | abrir en esa línea el editor indicado por la variable de entorno TEXEDIT |
1 … 9 | descartar los siguientes 1 a 9 tokens y continuar; la línea se vuelve a mostrar en el nuevo corte |
Los cuatro modos -interaction y cuándo usar cada uno
pdflatex --help enumera cuatro valores —batchmode, nonstopmode, scrollmode, errorstopmode— y el predeterminado es errorstopmode. Para una compilación dirigida por un script, -interaction=nonstopmode; para un trabajo de CI que no debe llenar el terminal, -interaction=batchmode. Solo dos ejes separan a los cuatro: si se detiene y si escribe en el terminal. La pareja peor entendida es scrollmode frente a nonstopmode. Medido: un documento que llama a \typein lee de verdad la respuesta del terminal bajo scrollmode y muere con ! Emergency stop. bajo nonstopmode. La línea divisoria no está en los errores sino en la entrada por terminal.
| Modo | ¿Se detiene? ¿Escribe en el terminal? |
|---|---|
errorstopmode | el predeterminado; se detiene en cada error con un prompt ? — para trabajo manual |
scrollmode | no se detiene ante errores pero sigue leyendo del terminal; útil para ojear una ejecución entera |
nonstopmode | nunca lee del terminal; si algo pide entrada, termina con ! Emergency stop. |
batchmode | nonstopmode más salida de terminal suprimida; el .log se escribe igualmente completo |
Decir que batchmode no imprime nada es casi cierto. Midiendo el mismo documento defectuoso en TeX Live 2024, el terminal recibe 1212 bytes bajo nonstopmode y 144 bytes bajo batchmode — lo que sobrevive es el rótulo de pdfTeX y entering extended mode, impresos antes de que el modo de interacción entre en vigor. El .log, en cambio, ocupa 4144 bytes en ambos casos, byte a byte idéntico, y el PDF se produce igual. Así que batchmode no descarta información: solo la mantiene fuera del terminal. De ahí la receta habitual en CI: compilar en modo batch, decidir el éxito por el código de salida de la sección siguiente y archivar el .log para el detalle. Los cuatro nombres son además primitivas de TeX, de modo que escribir \nonstopmode al principio del archivo surte el mismo efecto.
-halt-on-error y el código de salida
-halt-on-error abandona la compilación en el primer error. Verificado en TeX Live 2024: justo después del primer ! Undefined control sequence imprime ! ==> Fatal error occurred, no output PDF file produced! y termina, sin dejar PDF. El mismo documento con solo -interaction=nonstopmode informa de los cuatro errores y escribe un PDF igualmente, así que la opción sirve para que un documento roto no parezca una compilación correcta. También se midió el código de salida: 1 si hubo cualquier error, 0 si no hubo ninguno. No depende del modo —nonstopmode y batchmode se comportan igual— y las advertencias nunca lo alteran. De modo que una cadena pdflatex && … en un Makefile o en un trabajo de CI solo se detiene ante errores.
# interactive: stop at the first error and look at it
pdflatex -file-line-error -halt-on-error document.tex
# CI: quiet terminal, full log on disk, exit status decides
pdflatex -interaction=batchmode -halt-on-error -file-line-error document.tex
echo $? # 1 if any error occurred, 0 if noneLeer el .log: contiene más de lo que el terminal mostró
El .log conserva el párrafo de ayuda que el terminal nunca imprimió, así que cuando un mensaje resulta opaco no hace falta reproducirlo y teclear h: basta con abrir el registro. Medido en una ejecución: 938 bytes llegaron al terminal mientras el .log guardaba 3199, y la diferencia es en su mayor parte ese texto de ayuda. El efecto es máximo en un choque de opciones: el terminal solo muestra ! LaTeX Error: Option clash for package inputenc., mientras que el registro detalla con qué opciones se cargó el paquete la primera vez y cuáles se acaban de pedir. Esas cuatro líneas separan adivinar de saber.
% only the first line of this reaches the terminal
./oc1.tex:4: LaTeX Error: Option clash for package inputenc.
...
The package inputenc has already been loaded with options:
[utf8]
There has now been an attempt to load it with options
[latin1]
Adding the global options:
utf8,latin1
to your \documentclass declaration may fix this.Conocer la forma del registro completo también compensa. La primera línea nombra el motor, su versión y la fecha y hora de la ejecución; la siguiente muestra la invocación como **document.tex; a partir de ahí todo son paréntesis anidados — ( abre un archivo y ) lo cierra, de modo que el anidamiento responde a la pregunta de qué archivo arrastró un paquete. [1], [2] marcan páginas ya emitidas, y el final es el balance de memoria tras Here is how much of TeX's memory you used: seguido de Output written on document.pdf (1 page, 12817 bytes).. Quien no quiera enfrentarse a todo eso puede pasar la compilación por texfot, incluido en TeX Live, que reduce la salida a errores, advertencias y la línea de resumen final.
$ texfot pdflatex -interaction=nonstopmode two.tex
texfot: invoking: pdflatex -interaction=nonstopmode two.tex
This is pdfTeX, Version 3.141592653-2.6-1.40.26 (TeX Live 2024)
! Undefined control sequence.
l.3 First \foo
! Missing $ inserted.
<inserted text>
l.4 Second \bar
Output written on two.pdf (1 page, 23091 bytes).\listfiles y el bloque *File List*: contar lo que realmente se cargó
Basta un \listfiles en cualquier punto del preámbulo para que el .log gane al final una tabla *File List* que nombra cada archivo cargado con su fecha, versión y una descripción de una línea. Contado en TeX Live 2024: un article pelado carga 3 archivos (article.cls, size10.clo, l3backend-pdftex.def). Una sola línea de hyperref lo lleva a 33 — hyperref por sí solo arrastra 30 más. Con tikz son 34. Es el primer movimiento cuando un paquete que nunca se pidió aparece implicado en un conflicto. También es lo que conviene pegar al plantear una pregunta o informar de un fallo: la tabla revela de un vistazo cualquier discrepancia entre dos instalaciones.
% \listfiles goes anywhere in the preamble; this lands at the end of the .log
*File List*
article.cls 2023/05/17 v1.4n Standard LaTeX document class
size10.clo 2023/05/17 v1.4n Standard LaTeX file (size option)
amsmath.sty 2023/05/13 v2.17o AMS math features
hyperref.sty 2024-01-20 v7.01h Hypertext links for LaTeX
iftex.sty 2022/02/03 v1.0f TeX engine tests
***********Para una vista más fina se añade -recorder. Cada archivo abierto durante la compilación se escribe en un archivo .fls como línea INPUT — un documento cuyo único paquete es tikz produce 140. Donde \listfiles responde «qué paquetes se cargaron», .fls responde «qué archivos se tocaron», hasta los .tfm de fuentes y los archivos de configuración. El primero sirve para perseguir un choque de paquetes; el segundo, para averiguar dónde buscó realmente kpathsea.
\show, \showthe, \typeout: imprimir lo que TeX cree
\show\foo imprime la definición de \foo, y \showthe\textwidth el valor de una longitud o un contador. La salida acaba en el .log como > \LaTeX=macro: o > 345.0pt. — el > inicial es la marca, y 345,0 pt resulta ser el \textwidth predeterminado de article. Cuando no se recuerda cómo está definido ahora mismo un comando, \show gana a adivinar, y suele zanjar si quien redefinió fue la clase o un paquete. Para emitir mensajes propios están \typeout{…} y \message{…}; medido, \typeout coloca su texto en una línea propia mientras que \message lo pega a la línea en curso. El primero se lee mejor en depuración estilo printf; el segundo sirve para marcar un punto junto a un número de página.
\show\LaTeX % > \LaTeX=macro: ... (definition follows)
\showthe\textwidth % > 345.0pt. (article default)
\typeout{reached the theorem} % own line in log and terminal
\message{mark} % appended to the current line
\tracingall % dump every step to the log -- extremely verboseEl último recurso es \tracingall, que escribe en el registro cada paso de TeX: expansiones de macros, cambios de modo, intentos de corte de línea. En un documento de pocas páginas puede alcanzar decenas de megabytes, así que conviene activarlo justo antes del punto problemático y volver a \tracingnone justo después, o combinarlo con el paquete trace, que ordena la salida hasta hacerla legible. \tracingall responde a «en qué orden ocurrió esto», no a «qué macro tiene la culpa» — y una vez claro el orden, un solo \show suele zanjar lo demás.
Bisecar el documento: subir \end{document}
Cuando el mensaje por sí solo no basta, partir el documento en dos es el camino más corto: escriba un \end{document} adicional a media altura del cuerpo y todo lo posterior se ignora. Verificado en TeX Live 2024 — lo que siga a \end{document}, incluso un comando roto, nunca se lee. Ni siquiera hace falta borrar el original: basta deslizar la línea añadida arriba y abajo para cerrar el cerco por ambos lados. Diez movimientos reducen un documento de mil líneas a una sola. Si el sospechoso es el preámbulo, comente con % la mitad de las líneas \usepackage cada vez; y si los capítulos están separados con \include, use \includeonly{chapter3}.
\begin{document}
\input{chapters/intro}
\input{chapters/method}
\end{document} % <- added: bisect here, everything below is ignored
\input{chapters/results}
\input{chapters/discussion}
\end{document}Una vez reducido a la mitad, conviene seguir recortando hasta el ejemplo más pequeño que aún falle. Quite las líneas \usepackage de una en una, descarte el texto párrafo a párrafo, sustituya las figuras por example-image (incluido con graphicx) y los pasajes largos por lipsum: lo que queda suele ser una docena de líneas. A ese tamaño la causa normalmente salta a la vista; y si aun así no lo hace, esas líneas son exactamente lo que se pega en una pregunta. Recortar ya es diagnosticar — el arte de preguntar bien, y dónde hacerlo, corresponde a la página de la comunidad.