Undefinierte Verweise und doppelte Labels

Dort, wo eine Nummer stehen sollte, erscheint ??, und im Log steht LaTeX Warning: There were undefined references. Das ist die erste scheinbare Absurdität, der alle LaTeX-Anwender begegnen. Der Grund dafür, dass ein Verweis als ?? herauskommt: LaTeX entnimmt seine Nummern der .aux-Datei aus dem vorherigen Lauf. ?? und die klassische Frage „Warum muss ich zweimal übersetzen?“ sind also zwei Seiten derselben Medaille. Diese Seite behandelt diese Zweipassmechanik, die Unterscheidung von Label(s) may have changed, multiply defined und Citation ... undefined, die richtige Aufrufreihenfolge, sobald BibTeX oder Biber im Spiel ist, und – die übelste Falle überhaupt – jene Platzierung von \label, die ohne eine einzige Warnung die falsche Nummer druckt.

Warum muss zweimal übersetzt werden?

Weil LaTeX die Nummer von allem, was weiter hinten steht, erst kennt, wenn es das Dokument einmal von oben bis unten gelesen hat. Steht auf Seite 3 „siehe Kapitel 7“, ist zu diesem Zeitpunkt noch offen, auf welche Seite Kapitel 7 fällt. Also schreibt LaTeX im ersten Lauf jedes gefundene \label in eine .aux-Datei, liest sie zu Beginn des zweiten Laufs wieder ein und füllt erst dann die Nummern aus. Der erste Durchgang liefert deshalb zwangsläufig ?? – das ist Absicht, kein Fehler. Und das Problem ist zirkulär: Wechselt ein Verweis von ?? (zwei Zeichen) zu 12 (ebenfalls zwei, aber andere), ändert sich der Zeilenumbruch; ändert sich der Umbruch, ändern sich die Seitenzahlen; ändern sich die Seitenzahlen, ändern sich die Werte von \pageref. LaTeX löst den Kreis durch Iteration bis zur Stabilität, und die Meldung, die darüber Auskunft gibt, lautet LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. So lange erneut übersetzen, bis dieser Satz verschwindet – mehr Disziplin braucht es nicht.

Ein einziger Blick in eine .aux-Datei lässt den Mechanismus einrasten. Unten steht ein Auszug nach zwei Läufen eines Dokuments mit \section{The section}\label{sec:s} – zuerst reines LaTeX, dann dasselbe mit geladenem hyperref. \newlabel nimmt fünf Argumente, davon ist das erste die Nummer und das zweite die Seite. \ref holt schlicht das erste, \pageref das zweite. Mit hyperref enthält das dritte den Überschriftentext und das vierte den Ankernamen. \nameref{sec:s} kann „The section“ drucken, weil es dieses dritte Feld gibt, und \ref wird zum anklickbaren Link dank des vierten. Das erklärt zugleich, warum es stets unbedenklich ist, eine beschädigte .aux zu löschen und neu erzeugen zu lassen: Ihr Inhalt ist rein abgeleitet und entsteht bei jedem Lauf neu.

document.aux
% plain LaTeX: {number}{page}{}{}{}
\newlabel{sec:s}{{1}{1}{}{}{}}

% with hyperref: {number}{page}{title}{anchor}{}
\newlabel{sec:s}{{1}{1}{The section}{section.1}{}}

Die Läufe von Hand mitzuzählen ist Zeitverschwendung, weshalb ein Werkzeug entstand, das die Entscheidung übernimmt: latexmk. Es liest das Log und übersetzt so lange weiter, bis Rerun to get cross-references right verschwunden ist, und schiebt bei Bedarf BibTeX- oder Indexläufe dazwischen. Seine Herkunft ist reizvoll: Im Kopf des mit TeX Live 2024 ausgelieferten latexmk steht, dass das Original ein Skript namens go aus dem Jahr 1992 von David J. Musliner an der University of Michigan war. Danach überarbeitete es Evan McLean, 1998 übernahm John Collins, und die mitgelieferte Fassung trägt die Nummer 4.83 vom Januar 2024. Ein schlichter Ärger – „Wie oft soll ich das eigentlich übersetzen?“ – trägt seit über dreißig Jahren ein gepflegtes Werkzeug.

Die Warnungen unterscheiden: „noch nicht“ gegen „wirklich nicht vorhanden“

Der Test ist einfach: zweimal übersetzen und sehen, ob dieselbe Warnung überlebt. Eine Warnung, die nur im ersten Durchgang auftritt, ist normales Verhalten; eine, die im zweiten noch da ist, ist ein echtes Problem. Übersetzt man ein Dokument mit einem \ref{nope} (ein Label, das es nicht gibt) und einem \ref{sec:real} (eines, das es gibt), meldet der erste Lauf beide als undefiniert und schließt mit There were undefined references. sowie Label(s) may have changed. Rerun to get cross-references right. Im zweiten Lauf ist sec:real verschwunden, nur nope bleibt, und Label(s) may have changed fehlt. In der Kerneldatei latex.ltx gibt es nur eine Abschlussmeldung, There were undefined references, und sowohl ein fehlgeschlagenes \ref als auch ein fehlgeschlagenes \cite setzen dieselbe Marke. Eine Meldung über „undefined references“ kann also durchaus ein Literaturverweis sein.

log
% 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.
MeldungBedeutungWas zu tun ist
Label(s) may have changeddie Nummern haben sich noch nicht eingependelterneut übersetzen – mehr nicht
Reference `x' ... undefined\label{x} steht nicht in der .auxübersteht es den zweiten Lauf, Schreibweise oder Position prüfen
There were undefined referencesein \ref oder \cite blieb ungelöstdie Einzelwarnungen darüber lesen
Label `x' multiply defineddasselbe Label kommt mehrfach voreindeutig machen. Erscheint erst ab dem zweiten Lauf
Citation `x' ... undefineddieser Eintrag fehlt in der .bblbibtex oder biber laufen lassen, dann zweimal übersetzen
rerunfilecheck: File ... has changeddie Lesezeichendatei von hyperref hat sich geänderterneut übersetzen

Wenn ?? zwei Durchgänge übersteht

Es bedeutet, dass das Label tatsächlich nicht in der .aux steht. Die Prüfung dauert eine Sekunde: die .aux öffnen und nach \newlabel{ samt Namen suchen. Fehlt es, liegt das Problem beim \label; ist es vorhanden und es erscheint trotzdem ??, liegt eine Abweichung in der Schreibweise beim \ref vor. Nebenbei: Dass ?? fett gedruckt wird, ist Absicht. Das \@setref des Kernels schreibt \nfss@text{\reset@font\bfseries ??}bewusst fett, damit es nicht übersehen wird, weshalb es selbst in einem ausgedruckten Entwurf sofort auffällt. Die typischen Gründe, warum ein Label nie in der .aux landet, folgen unten.

  • Ein Schreibunterschied. \label{fig:setup} und \ref{fig:Setup} sind verschiedene Labels; die Namen unterscheiden Groß- und Kleinschreibung.
  • Die Datei ist durch \includeonly ausgeschlossen. Labels einer ausgeschlossenen Datei werden nie geschrieben, Verweise darauf bleiben bei ??. Solange der Ausschluss gilt, ist ?? das korrekte Verhalten.
  • Eine veraltete oder beschädigte .aux. Das folgt auf einen abgebrochenen Lauf oder einen Wechsel von Klasse oder Paket. .aux, .toc und .out löschen, dann zweimal übersetzen.
  • Das \label steht in einem beweglichen Argument. Direkt in ein Überschriften- oder Bildunterschriftsargument geschrieben, kann es in die .toc kopiert werden und dort etwas anderes bedeuten. Sicher ist die Form hinter \caption, außerhalb der Klammern.
  • Es wird die falsche Datei übersetzt. In einem Mehrdateiprojekt aktualisiert das Übersetzen einer Kinddatei die .aux der Elterndatei nicht. Immer vom Elterndokument aus bauen.
  • Der Zitatschlüssel fehlt in der .bib. Das erscheint als [?], nicht als ??; die Ausgabe von bibtex auf I didn’t find a database entry prüfen.

Ein \label vor \caption druckt stumm die falsche Nummer

\label gehört stets hinter \caption. Davor gesetzt gibt es keinen Fehler, keine Warnung – und eine völlig andere gedruckte Nummer. Das lässt sich messen. Ein Dokument mit drei \section-Befehlen und zwei Abbildungen, im ersten \label vor \caption, im zweiten dahinter, zweimal übersetzt, ergibt in der .aux: \newlabel{fig:before}{{3}{1}{}{}{}} und \newlabel{fig:after}{{2}{1}{}{}{}}. Die erste hätte Abbildung 1 sein sollen, notiert wurde aber 3 – die Nummer des vorangehenden Abschnitts. Und LaTeX gab null Warnungen aus. Das PDF entsteht sauber, und im Text steht selbstbewusst „Abbildung 3“. Der Mechanismus: \label hält den Wert des gerade gültigen Zählers fest, doch das Umschalten auf den Zähler figure und dessen Weiterzählen erledigt \caption (es ruft \refstepcounter auf). Vor \caption stammt das jüngste \refstepcounter von \section, also wird die Abschnittsnummer notiert. Solche Fehler fallen erst auf, wenn eine Gutachterin schreibt: „Sie verweisen auf Abbildung 3, aber Abbildung 3 zeigt etwas anderes“ – genau deshalb lohnt die Regel \label unmittelbar nach \caption.

latex
\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 in Umgebungen: \item, equation, \section*

Es gibt nur eine Regel: \label unmittelbar hinter den Befehl setzen, der den Zähler weiterzählt. In enumerate also direkt hinter \item, bei einer Gleichung innerhalb der Umgebung, bei einem Abschnitt direkt hinter \section{…}. Auch hier passieren Fehler lautlos. Ein \label{it:bad} gleich nach \begin{enumerate} und vor dem ersten \item liefert nach zwei Läufen in der .aux \newlabel{it:bad}{{1}{1}{}{}{}} – keine Punktnummer, sondern die 1 des vorangehenden Abschnitts. Wieder null Warnungen. Dasselbe gilt für \section*{…}: Eine Sternüberschrift zählt keinen Zähler weiter, also greift ein \label dahinter die Nummer des letzten nummerierten Abschnitts davor ab. Wer eine Sternüberschrift referenzieren will, kombiniert sie mit \phantomsection (aus hyperref) und \addcontentsline – oder gestaltet das Dokument so, dass sie nicht referenziert wird. Die verbreitete Gewohnheit, Labelnamen mit fig:, tab:, sec:, eq:, it: zu präfigieren, dient nicht nur der Ordnung: \ref{fig:x} macht die eigene Absicht auf dem Papier sichtbar – gemeint war eine Abbildung. Passt die gedruckte Nummer nicht zu einer Abbildung, fällt es dank des Präfixes auf.

Label ... multiply defined erscheint erst ab dem zweiten Lauf

Dasselbe \label{x} existiert an zwei oder mehr Stellen, und \ref{x} zeigt auf eine davon – die zuletzt gelesene. Eine Eigenschaft ist dabei wichtig: Beim ersten Lauf unmittelbar nach dem Löschen der .aux erscheint diese Warnung überhaupt nicht. Im Test hier meldete ein einzelner Durchgang ohne vorhandene .aux null multiply defined. Die Warnung entsteht erst zu Beginn des zweiten Laufs, wenn LaTeX die .aux einliest und ein bereits definiertes Label erneut definieren soll. „Einmal übersetzt, keine Warnung gesehen“ ist also kein Beleg für eindeutige Labels. Am Dokumentende steht zusätzlich die Zusammenfassung LaTeX Warning: There were multiply-defined labels. Die Ursache ist fast immer Copy-and-paste: eine kopierte Kapiteldatei, ein zweimal per \include eingebundenes File oder ein subfiles-Dokument, das von Eltern- und Kinddatei zugleich geladen wird. Vorbeugend hilft ein dateiweises Präfix wie intro:fig:setup, denn dann ist ein in ein anderes Kapitel kopiertes Label auf einen Blick falsch.

Citation ... undefined und die Aufrufreihenfolge von BibTeX/Biber

Bleibt ein Zitat bei [?] stehen, braucht es vier Läufe: pdflatex, bibtex, pdflatex, pdflatex. Querverweise brauchen zwei, Zitate vier, weil dazwischen ein weiteres Programm laufen muss. Das erste pdflatex schreibt die Liste der zitierten Schlüssel in die .aux und protokolliert No file document.bbl. neben Citation ... undefined. Dann gleicht bibtex diese Liste mit der .bib ab und erzeugt eine .bbl, das formatierte Literaturverzeichnis. Der dritte Lauf liest die .bbl erstmals ein, vergibt jedem Eintrag eine Nummer und schreibt sie in die .auxdie \cite-Befehle im Text sind zu diesem Zeitpunkt noch ungelöst. Erst der vierte Lauf füllt sie. In einem echten Log zeigte der dritte Lauf weiterhin Citation ... undefined samt Label(s) may have changed. Rerun to get cross-references right., der vierte war sauber. Mit biblatex tritt biber an die Stelle von bibtex, die Struktur der Folge bleibt gleich. Wird ein nicht vorhandener Schlüssel zitiert, sagt es bibtex deutlich: Warning--I didn’t find a database entry for "missingkey". Bei dieser Art von Problem entscheidet es, die Ausgabe von bibtex statt der von LaTeX zu lesen.

terminal
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 document

Die Wahl zwischen \ref, \eqref, \cref, \nameref, \vref – und die Ladereihenfolge

Nacktes \ref druckt nur eine Nummer. Das Wort „Abbildung“ oder „Gleichung“ und etwaige Klammern muss man selbst tippen, und alles Handgetippte gerät irgendwann aus dem Tritt. Dafür gibt es eine Schicht von Befehlen, die die Tabelle unten auflistet – doch die Ladereihenfolge ist strikt: cleveref muss nach hyperref und ebenso nach varioref geladen werden. Bei falscher Reihenfolge diagnostiziert sich cleveref.sty selbst: ! Package cleveref Error: cleveref must be loaded after hyperref!. oder ! Package cleveref Error: cleveref must be loaded after varioref!. (beides hier nachgestellt). Richtig ist hyperrefvariorefcleveref. Als Praxisregel gilt: In einem neuen Dokument sorgt eine einheitliche Nutzung von cleveref für die wenigsten Unfälle. \cref{eq:e} ergibt „eq. (1)“, \Cref{sec:s} ergibt „Section 1“; das passende Wort kommt je nach Zielsorte automatisch, sodass ein Umstellen der Gliederung keine veralteten Formulierungen hinterlässt. In einem übernommenen Mehrautorenmanuskript ist es dagegen realistischer, Mischformen zuzulassen und damit zu rechnen, dass Mitautoren weiterhin \ref schreiben.

BefehlBeispielausgabeBereitgestellt von / Hinweis
\ref1der Kernel; nur die Nummer. Mit hyperref wird daraus ein Link
\pageref1der Kernel; das zweite .aux-Feld, also die Seite
\eqref(1)amsmath; eine Gleichungsnummer samt Klammern
\crefeq. (1)cleveref; ergänzt das zur Zielsorte passende Wort
\CrefSection 1cleveref; großgeschriebene Form für den Satzanfang
\autorefsection 1hyperref; einfacher als \cref, kann keine Bereiche zusammenfassen
\namerefThe sectionnameref, von hyperref geladen; druckt den Überschriftentext
\vref1 on the previous pagevarioref; auf derselben Seite nur die Nummer, sonst zusätzlich eine Seitenangabe
preamble
% load order matters: hyperref, then varioref, then cleveref
\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{varioref}
\usepackage{cleveref}    % must come last of the three