Runaway argument? ist der eine LaTeX-Fehler, dessen Zeilennummer nicht zu trauen ist – manchmal steht dort überhaupt keine Zeilennummer. Fehlt eine schließende }, geht TeX auf die Suche danach, verschlingt dabei den Text und schreit erst auf, wenn nichts mehr übrig ist. Gemeldet wird dann nicht die Stelle des Fehlers, sondern die Stelle, an der TeX am Ende war. Zum Ausgleich druckt TeX genau den Text zurück, den es verschlungen hat: die Zeile direkt hinter Runaway argument? – und das ist die eigentliche Landkarte. Diese Seite zeigt, wie man sie liest, warum die Meldung einen nie getippten Namen wie ! Paragraph ended before \@sect was complete nennt, und wie sich \newcommand* absichtlich als Stolperdraht einsetzen lässt.
Den runaway text lesen, nicht die Zeilennummer
Die Zeile hinter Runaway argument? beginnt genau ein Zeichen hinter der Klammer, die nicht geschlossen wurde. Sucht man die ersten Wörter dieser Zeile im Editor, hat man die verirrte { gefunden. Das ist schneller und weit verlässlicher, als auf die Zeilennummer zu starren. Unten steht echte Log-Ausgabe zu einem nicht geschlossenen \textbf{.
Runaway argument?
{an important point that never closes. Another sentence on the next l\ETC.
! File ended while scanning use of \textbf .
<inserted text>
\par
<*> t6.texZwei Dinge fallen dort auf. Erstens das abschließende \ETC. – TeXs Markierung dafür, dass der verschlungene Text zu lang war und an der Bildschirmbreite abgeschnitten wurde. Zweitens steht in der letzten Zeile keine Zeilennummer wie l.6, sondern der Dateiname, <*> t6.tex. Diese Form bedeutet, dass TeX die Eingabe restlos aufgebraucht hat: Es hat bis zum Dateiende gelesen, die verirrte { liegt also weit oben. Eine Zeilennummer erscheint nur, wenn unterwegs etwas den Lauf gestoppt hat.
Paragraph ended before ... was complete: eine Leerzeile in einem kurzen Argument
Die Meldung besagt, dass im Argument eine Leerzeile steht. Für TeX ist eine Leerzeile kein Weißraum, sondern ein Token namens \par, und \par darf in einem „kurzen“ Argument nicht vorkommen – dem Argument eines ohne \long definierten Makros. Rutscht also eine Leerzeile in ein \section{...}, wo nur ein Zeilenumbruch gemeint war, gibt es einen Runaway, obwohl die } sauber dasteht.
Runaway argument?
{A heading that runs on
! Paragraph ended before \@sect was complete.
<to be read again>
\par
l.5 and on across a blank line}Den Namen \@sect hat gewiss niemand je getippt. Tatsächlich ist \section selbst als \long definiert und lässt eine Leerzeile durch – nicht \long ist das interne Makro, das die Arbeit übernimmt: \@sect (ein \show unter TeX Live 2024 bestätigt beides). In der Meldung steht nicht der getippte Befehl, sondern das interne Makro, das das Argument tatsächlich eingesammelt hat. Ähnlich fremde Namen tauchen rund um \caption, \footnote und das Inhaltsverzeichnis auf. Davon nicht beirren lassen – stattdessen die Zeile Runaway argument? lesen.
Warum \par in einem Argument überhaupt verboten ist
Die Einschränkung besteht nicht, um zu ärgern, sondern wurde absichtlich eingebaut, um vergessene schließende Klammern zu fangen. Victor Eijkhouts TeX by Topic, das TeX Live beiliegt, schreibt über die Regel, dass \par in Argumenten verboten ist, sie „is useful … in locating forgotten closing braces“, und fügt an: „the empty line generates a \par, which most of the times means that a closing brace has been forgotten“. Ein kurzes Argument ist mit anderen Worten eine Sicherung, die den Runaway früh anhält. Ohne diese Regel würde eine einzige fehlende { genügen, damit TeX schweigend ein ganzes Dokument verschlingt und ohne jeden Hinweis stehen bleibt.
Ein kleines Experiment zeigt, wie wörtlich der Mechanismus arbeitet. TeX verweigert das Token mit dem Namen \par selbst, nicht die Vorstellung, einen Absatz zu beenden. \endgraf ist ein Alias, das sich genau wie \par verhält – in einem kurzen Argument geschrieben passiert damit trotzdem nichts; ein \par an derselben Stelle löst sofort ! Paragraph ended before ... was complete aus. TeX vergleicht schlicht Tokennamen – und genau das macht eine Leerzeile, ansonsten bedeutungsloser Weißraum, zu einem zuverlässig erkennbaren Signal.
Der Unterschied zu File ended while scanning use of ...
Auf Runaway argument? können zwei verschiedene Zeilen folgen, und sie verraten, wie weit der Runaway gekommen ist. Von einer Leerzeile unterwegs gestoppt, erscheint Paragraph ended before ... was complete; gar nicht gestoppt, erscheint File ended while scanning use of .... Ein feinerer Hinweis steht eine Zeile darunter: <to be read again> \par heißt, TeX hat ein aus einer Leerzeile stammendes \par gelesen und zurückgeschoben; <inserted text> \par heißt, die Eingabe war erschöpft und TeX hat ein eigenes \par eingefügt. Das erste sagt, die Ursache liegt nah, das zweite, sie liegt weit entfernt.
| Meldung | Bedeutung | Worauf das Log zeigt |
|---|---|---|
Runaway argument? | das Argument wurde nie abgeschlossen; der verschlungene Text folgt stets in der nächsten Zeile | der Anfang dieser Zeile liegt direkt hinter der offenen { |
Paragraph ended before ... was complete | eine Leerzeile (ein \par) geriet in ein kurzes Argument | die Zeilennummer der Leerzeile; die { steht etwas darüber |
File ended while scanning use of ... | bis zum Dateiende tauchte keine } auf | keine Zeilennummer, sondern <*> Dateiname; die { liegt weit oben |
\newcommand* bewusst als Stolperdraht einsetzen
\newcommand erzeugt ein \long-Makro, \newcommand* ein kurzes. Ein \show zeigt beim ersten \long macro: und beim zweiten schlicht macro:. Beim Runaway wird der Unterschied deutlich. Fehlt die schließende { eines ohne Stern definierten Makros, marschiert TeX ungerührt über Leerzeilen hinweg bis zum Dateiende und endet mit ! Emergency stop. – ganz ohne PDF. Mit Stern hält es an der ersten Leerzeile, nennt das eigene Makro, und der Lauf kommt trotzdem durch. Das ist kein Unterschied von ein paar Log-Zeilen, sondern der zwischen einem Verdachtsbereich von wenigen Dutzend Zeilen und dem gesamten Dokument.
% short: the runaway stops at the first blank line, and the run survives
\newcommand*{\keyword}[1]{\textbf{#1}}
% ! Paragraph ended before \keyword was complete.
% <to be read again>
% \par
% long (the default): the runaway reaches end of file
\newcommand{\keyword}[1]{\textbf{#1}}
% ! File ended while scanning use of \keyword.
% ! Emergency stop.Die praktische Regel ist einfach: Jedes Makro, dessen Argument keine ganzen Absätze aufnehmen muss, mit \newcommand* definieren. Überschriften, Fachbegriffe, Einheiten, kurze Beschriftungen – damit sind die meisten selbst geschriebenen Makros abgedeckt. Die Form ohne Stern bleibt Makros vorbehalten, die Absätze aufnehmen sollen, etwa der Text eines Kastens. Was der Stern für sich bedeutet und wie er sich zu \renewcommand verhält, behandelt die Seite „Makros definieren“. Zu beachten ist außerdem: \verb oder eine verbatim-Umgebung in einem Argument geht auf ganz andere Weise kaputt – der Grund steht auf der Seite „Unveränderte Ausgabe“.
Wie sich die fehlende Klammer tatsächlich finden lässt
Zuerst nach dem Anfang des runaway text suchen; führt das nicht weiter, den Inhalt lesen. Im verschlungenen Text steckt oft etwas, das in einem Argument nichts zu suchen hat, und genau das grenzt den Bereich ein. Erscheint etwa \begin {document} im runaway text, liegt die offene { in der Präambel – wer den Rumpf eines \newcommand nicht schließt, bekommt genau dieses Bild. Erscheint \end {document}, hat der Runaway das Dokumentende erreicht. Ist die Gegend erst eingegrenzt, zahlt sich die Klammerpaarung des Editors aus: den Cursor auf eine verdächtige { setzen und sehen, wo das Gegenstück landet. Reicht auch das nicht, die Hälfte des Dokuments auskommentieren, neu übersetzen und die noch fehlerhafte Hälfte erneut halbieren; nach wenigen Runden ist die Stelle gefunden.
Runaway argument?
{Hello \begin {document} Body. \end {document}
! File ended while scanning use of \@argdef.