Aparece un ?? donde debería haber un número, y el log dice LaTeX Warning: There were undefined references. Es el primer absurdo aparente con el que se topa todo usuario de LaTeX. Si una referencia sale como ?? es porque LaTeX toma sus números del archivo .aux que dejó la ejecución anterior. Así que ?? y la pregunta clásica «¿por qué tengo que compilar dos veces?» son las dos caras de una misma moneda. Esta página trata ese mecanismo de dos pasadas, cómo distinguir Label(s) may have changed, multiply defined y Citation ... undefined, el orden de ejecución correcto en cuanto entra BibTeX o Biber y —la trampa más temible— esa colocación de \label que imprime el número equivocado sin emitir un solo aviso.
¿Por qué hay que compilar dos veces?
Porque LaTeX no conoce el número de nada que venga más adelante hasta haber leído el documento de arriba abajo una vez. Escriba «véase el capítulo 7» en la página 3 y, en ese momento, aún no está decidido en qué página caerá el capítulo 7. Así que LaTeX escribe en la primera pasada todos los \label que encuentra en un archivo .aux, lo vuelve a leer al comienzo de la segunda pasada y solo entonces rellena los números. La primera pasada da, por tanto, ?? con toda seguridad: es el diseño, no un fallo. Y el problema es circular: cuando una referencia pasa de ?? (dos caracteres) a 12 (también dos, pero distintos), cambia el corte de líneas; si cambia el corte, cambian los números de página; si cambian, cambian los valores de \pageref. LaTeX resuelve el círculo iterando hasta que se estabiliza, y el mensaje que lo informa es LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. Vuelva a ejecutar hasta que esa frase desaparezca: en eso consiste toda la disciplina.
Basta con asomarse una vez a un archivo .aux para que todo encaje. Abajo hay un extracto tras dos pasadas de un documento que contiene \section{The section}\label{sec:s}: primero en LaTeX puro y luego con hyperref cargado. \newlabel toma cinco argumentos, de los cuales el primero es el número y el segundo la página. \ref extrae sencillamente el primero; \pageref, el segundo. Con hyperref, el tercero guarda el texto del título y el cuarto el nombre del ancla. \nameref{sec:s} puede imprimir «The section» gracias a ese tercer campo, y \ref se convierte en un enlace pulsable gracias al cuarto. Esto explica además por qué borrar un .aux dañado y dejar que se reconstruya siempre es seguro: todo su contenido es derivado y se regenera en cada pasada.
% plain LaTeX: {number}{page}{}{}{}
\newlabel{sec:s}{{1}{1}{}{}{}}
% with hyperref: {number}{page}{title}{anchor}{}
\newlabel{sec:s}{{1}{1}{The section}{section.1}{}}Contar las pasadas a mano es desperdiciar a una persona, así que nació una herramienta que decide por usted: latexmk. Lee el log y sigue compilando hasta que desaparece Rerun to get cross-references right, intercalando cuando hace falta BibTeX o el procesado del índice. Su procedencia tiene su encanto: la cabecera del latexmk que se distribuye con TeX Live 2024 registra que el original fue un script de 1992 llamado go, escrito por David J. Musliner en la Universidad de Michigan. Evan McLean lo remodeló después, John Collins tomó el relevo en 1998 y la versión incluida es la 4.83, de enero de 2024. Una molestia sencilla —«¿cuántas veces hay que compilar esto?»— sostiene una herramienta mantenida desde hace más de treinta años.
Distinguir los avisos: «todavía no» frente a «realmente falta»
La prueba es simple: compile dos veces y vea si el mismo aviso sobrevive. Un aviso que solo aparece en la primera pasada es comportamiento normal; uno que sigue ahí en la segunda es un problema real. Compile un documento con un \ref{nope} (etiqueta inexistente) y un \ref{sec:real} (etiqueta existente): la primera pasada informa de ambos como indefinidos y cierra con There were undefined references. y Label(s) may have changed. Rerun to get cross-references right. En la segunda pasada sec:real ha desaparecido, solo queda nope y Label(s) may have changed se ha esfumado. En el archivo del núcleo latex.ltx hay un único resumen final, There were undefined references, y tanto un \ref fallido como un \cite fallido levantan la misma bandera. Así que un mensaje sobre «undefined references» puede referirse perfectamente a una cita.
% first run
LaTeX Warning: Reference `nope' on page 1 undefined on input line 3.
LaTeX Warning: Reference `sec:real' on page 1 undefined on input line 5.
LaTeX Warning: There were undefined references.
LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
% second run -- sec:real is resolved, nope is a real problem
LaTeX Warning: Reference `nope' on page 1 undefined on input line 3.
LaTeX Warning: There were undefined references.| Mensaje | Significado | Qué hacer |
|---|---|---|
Label(s) may have changed | los números aún no se han estabilizado | compilar otra vez, nada más |
Reference `x' ... undefined | \label{x} no está en el .aux | si sobrevive a la segunda pasada, sospeche de la ortografía o la colocación |
There were undefined references | algún \ref o \cite no se resolvió | lea los avisos individuales de más arriba |
Label `x' multiply defined | la misma etiqueta aparece dos o más veces | hágala única. Solo aparece a partir de la segunda pasada |
Citation `x' ... undefined | esa entrada no está en el .bbl | ejecute bibtex o biber y compile dos veces más |
rerunfilecheck: File ... has changed | el archivo de marcadores de hyperref cambió | compile otra vez |
Cuando ?? sobrevive a dos pasadas
Significa que la etiqueta realmente no está en el .aux. La comprobación lleva un segundo: abra el .aux y busque \newlabel{ seguido del nombre. Si falta, el problema está en el lado del \label; si está y aun así sale ??, el problema es una diferencia de escritura en el lado del \ref. De paso: que ?? se imprima en negrita es intencionado. El \@setref del núcleo escribe \nfss@text{\reset@font\bfseries ??}, deliberadamente en negrita para que no pueda pasarse por alto, y por eso salta a la vista incluso en un borrador impreso. Abajo están las razones típicas por las que una etiqueta nunca llega al .aux.
- Una diferencia de escritura.
\label{fig:setup}y\ref{fig:Setup}son etiquetas distintas; los nombres distinguen mayúsculas de minúsculas. - El archivo está excluido por
\includeonly. Las etiquetas de un archivo excluido no se escriben nunca, y las referencias a ellas se quedan en??. Mientras la exclusión está activa,??es el comportamiento correcto. - Un
.auxobsoleto o dañado. Ocurre tras una pasada interrumpida o un cambio de clase o de paquete. Borre.aux,.tocy.out, y compile dos veces. - El
\labelestá dentro de un argumento móvil. Escrito directamente en el argumento de un título o de una leyenda, puede copiarse al.tocy significar allí otra cosa. La forma segura es después de\caption, fuera de sus llaves. - Está compilando el archivo equivocado. En un proyecto de varios archivos, compilar un hijo por separado no actualiza el
.auxdel padre. Construya siempre desde el documento padre. - La clave bibliográfica no está en el
.bib. Eso se manifiesta como[?]y no como??; busqueI didn’t find a database entryen la salida debibtex.
Un \label antes de \caption imprime el número equivocado, en silencio
Ponga siempre \label después de \caption. Colocado antes, no da error ni aviso, e imprime un número completamente distinto. Esto se puede medir. Tome un documento con tres \section y dos figuras, ponga \label antes de \caption en la primera y después en la segunda, compile dos veces y el .aux dirá: \newlabel{fig:before}{{3}{1}{}{}{}} y \newlabel{fig:after}{{2}{1}{}{}{}}. La primera debería haber sido la figura 1, pero registró 3, el número de la sección anterior. Y LaTeX emitió cero avisos. El PDF se genera sin problemas y el texto afirma con aplomo «figura 3». El mecanismo: \label anota el valor del contador vigente en ese instante, pero cambiar al contador figure e incrementarlo es tarea de \caption (que llama a \refstepcounter). Antes de \caption, el último \refstepcounter ejecutado fue el de \section, así que se anota el número de sección. Este es el tipo de fallo que se descubre cuando un revisor escribe «dice que veamos la figura 3, pero la figura 3 es otra cosa», y por eso vale la pena memorizar la regla \label inmediatamente después de \caption.
\begin{figure}[h]
\includegraphics{fig.pdf}
\caption{The right way round}
\label{fig:ok} % after \caption -- records the figure number
\end{figure}
\begin{figure}[h]
\label{fig:broken} % before \caption -- records the SECTION number
\includegraphics{fig.pdf}
\caption{Silently wrong}
\end{figure}\label dentro de entornos: \item, equation, \section*
Solo hay una regla: coloque \label inmediatamente después del comando que incrementa el contador. En enumerate, justo tras \item; en una ecuación, dentro del entorno; en una sección, justo tras \section{…}. También aquí los errores son silenciosos. Ponga \label{it:bad} inmediatamente después de \begin{enumerate}, antes del primer \item, compile dos veces y el .aux registra \newlabel{it:bad}{{1}{1}{}{}{}}: no un número de ítem, sino el 1 de la sección precedente. De nuevo, cero avisos. Lo mismo ocurre con \section*{…}: un título con asterisco no incrementa contador alguno, así que un \label posterior recoge el número de la última sección numerada anterior. Para referenciar un título con asterisco, combínelo con \phantomsection (de hyperref) y \addcontentsline, o diseñe el documento para no referenciarlo. La extendida costumbre de anteponer fig:, tab:, sec:, eq:, it: a los nombres de etiqueta no es solo cuestión de orden: escribir \ref{fig:x} deja su intención a la vista en la página: quería señalar una figura. Si el número impreso no es el de una figura, es el prefijo lo que le permite advertirlo.
Label ... multiply defined solo aparece a partir de la segunda pasada
El mismo \label{x} existe en dos o más sitios, y \ref{x} señala a uno de ellos: el leído en último lugar. Y tiene una propiedad que conviene saber: en una primera pasada justo después de borrar el .aux, este aviso no aparece en absoluto. En la medición hecha aquí, una única pasada sin .aux presente informó de cero multiply defined. El aviso surge al comienzo de la segunda pasada, cuando LaTeX relee el .aux y se encuentra definiendo una etiqueta ya definida. Así que «compilé una vez y no vi ningún aviso» no prueba que sus etiquetas sean únicas. Al final del documento hay además un resumen: LaTeX Warning: There were multiply-defined labels. La causa es casi siempre copiar y pegar: un archivo de capítulo duplicado, un mismo archivo incluido dos veces con \include, o un documento subfiles cargado tanto por el padre como por el hijo. La costumbre preventiva es un prefijo por archivo —intro:fig:setup—, porque entonces una etiqueta pegada en otro capítulo salta a la vista.
Citation ... undefined y el orden de ejecución de BibTeX/Biber
Si una cita se queda en [?], hacen falta cuatro pasadas: pdflatex, bibtex, pdflatex, pdflatex. Las referencias cruzadas necesitan dos; las citas, cuatro, porque en medio tiene que ejecutarse otro programa. El primer pdflatex escribe la lista de claves citadas en el .aux y registra No file document.bbl. junto a Citation ... undefined. Después bibtex coteja esa lista con el .bib y produce un .bbl, la bibliografía ya formateada. La tercera pasada lee el .bbl por primera vez, asigna un número a cada entrada y lo escribe en el .aux: en ese momento los \cite del cuerpo siguen sin resolver. Solo la cuarta pasada los rellena. En un log real, la tercera pasada seguía mostrando Citation ... undefined junto con Label(s) may have changed. Rerun to get cross-references right., y la cuarta salió limpia. Con biblatex se llama a biber en lugar de a bibtex, pero la forma de la secuencia es la misma. Cite una clave inexistente y bibtex se lo dirá: Warning--I didn’t find a database entry for "missingkey". Para esta clase de problema, leer la salida de bibtex en vez de la de LaTeX es lo decisivo.
pdflatex document # writes the cited keys into document.aux
bibtex document # reads document.aux + refs.bib, writes document.bbl
pdflatex document # reads the .bbl, numbers the entries
pdflatex document # finally resolves every \cite in the text
# with biblatex, swap the second line for:
# biber documentElegir entre \ref, \eqref, \cref, \nameref, \vref y el orden de carga
Un \ref pelado imprime solo un número. La palabra «figura» o «ecuación» y los paréntesis corren de su cuenta, y todo lo tecleado a mano acaba desajustándose. Existe una capa de comandos para cubrir ese hueco, recogida en la tabla siguiente, pero el orden de carga es estricto: cleveref debe ir después de hyperref y también después de varioref. Si el orden es incorrecto, cleveref.sty se diagnostica solo: ! Package cleveref Error: cleveref must be loaded after hyperref!. o ! Package cleveref Error: cleveref must be loaded after varioref!. (ambos reproducidos aquí). El orden correcto es hyperref → varioref → cleveref. Como guía práctica, en un documento nuevo, unificarse en cleveref es lo que menos accidentes causa: \cref{eq:e} da «eq. (1)» y \Cref{sec:s} da «Section 1», aportando la palabra correcta según el tipo de destino, de modo que reordenar la estructura nunca deja una redacción obsoleta. En un original colectivo heredado, en cambio, es más realista aceptar la mezcla y contar con que los coautores sigan escribiendo \ref.
| Comando | Salida de ejemplo | Lo aporta / advertencia |
|---|---|---|
\ref | 1 | el núcleo; solo el número. Se convierte en enlace si se carga hyperref |
\pageref | 1 | el núcleo; el segundo campo del .aux, es decir, la página |
\eqref | (1) | amsmath; un número de ecuación con sus paréntesis |
\cref | eq. (1) | cleveref; aporta la palabra que corresponde al tipo de destino |
\Cref | Section 1 | cleveref; forma con mayúscula para el inicio de frase |
\autoref | section 1 | hyperref; más simple que \cref y no agrupa rangos |
\nameref | The section | nameref, cargado por hyperref; imprime el texto del título |
\vref | 1 on the previous page | varioref; solo el número en la misma página, con una mención de página si el destino está en otra parte |
% load order matters: hyperref, then varioref, then cleveref
\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{varioref}
\usepackage{cleveref} % must come last of the three