# Comment after fragile \end{frame} breaks beamer

Today I spent more time than I would like to acknowledge being beaten by a comment in the code...

I was trying to insert some verbatim in a presentation and was getting this error:

Runaway argument?
! File ended while scanning use of \next.


Then, reducing the whole thing to a MWE I got this:

\documentclass{beamer}

\begin{document}

\begin{frame}[fragile]
Hello :)
\end{frame}% NO :(

\end{document}


and the error persisted.

Then, when I removed the comment after the \end{frame} the whole thing worked.

Can someone explain what happens here?

Disclaimer: no, I don't need the comment there :P

• That's a common problem when grabbing things to be treated verbatim as long as you want to do more than the original verbatim environment: verbatim mode is still in force when \end{frame} is scanned, because basically the input is examined line by line. – egreg Feb 12 '18 at 22:22
• @egreg But even without verbatim? The example does not have verbatim and it doesn't work... – Phelype Oleinik Feb 12 '18 at 22:30
• fragile frames are grabbed verbatim for saving them in an auxiliary file to be read back in. – egreg Feb 12 '18 at 22:34
• @egreg I found a .vrb file that contains Hello :) \end{frame}% NO :( \end{document}, so I presume that beamer searches for a line with exactly \end{frame}. Am I correct? – Phelype Oleinik Feb 12 '18 at 22:44
• I guess this is the reason. Indeed, if you try \end {frame}, the error is the same. – egreg Feb 12 '18 at 23:06

After digging a little in beamer's innards I found the answer to be, as egreg pointed out, the verbatim processor.

For [fragile] frames, beamer uses its verbatim processor, located in beamerbaseverbatim.sty. Beamer has a neat verbatim processor:

\protected\long\gdef\beamer@processframeline#1^^M{%
\edef\beamer@test{\beamer@strip@whitespace#1\beamer@strip@stop}%
\ifx\beamer@test\beamer@stopframe%
\let\next=\beamer@framewritten%
\else%
\immediate\write\beamer@verbatimfileout{#1}%
\let\next=\beamer@processframeline%
\fi%
\next%
}%


The processor is a delimited macro that will read everything up to a carriage return character (new line). The read content is stored in \beamer@test and compared to \beamer@stopframe which is, most of the time, defined as:

\xdef\beamer@stopframe{\string\\end\string\{frame\string\}}


which expands to the exact string \ e n d { f r a m e }.

The processor compares \beamer@test with \beamer@stopframe and if they are different the content of \beamer@test is written to \beamer@verbatimfileout (the .vrb file) and the \next macro is \let to be the processor, and it recursively calls itself to continue reading. Otherwise, if \beamer@test is the string \end{frame}, the processor exits normally.

The error happens because the processor does not ignore comments (they may be required in verbatim contexts!), so the processor compares \end{frame} with \end{frame}% NO :(, which obviously fails, and keeps reading past the \end{frame}.

Two things can happen now:

First, this is the last frame, so the processor will never find a matching \end{frame} and the ! File ended while scanning use of \next. error will appear and the compilation stops.

Second and more painful, there is another frame which will have the droids \end{frame} the processor was looking for. But in this case, the \next will be \let to \beamer@framewritten, which essentially reads the content of the .vrb file back to the frame. But the contents will be something like:

Hello :)
\end{frame}% NO :(
\begin{frame}
Hello again!


which will make things go wild :)

## TL;DR

Remember kids, when using [fragile] frames, the \end{frame} must be the only thing in the line. No leading spaces nor comments allowed (trailing spaces are gobbled by TeX).

As samcarter noted in her comment, the current version of Beamer allows leading and trailing whitespaces and tabs. The \beamer@strip@whitespace macro will eat spaces and tabs before the comparison with \beamer@stopframe.