[Tex/LaTex] beamer: using \note<> and frame labels together creates multiply-defined labels

beamercross-referencing

This question is very similar to this one. However, since the solution provided there cannot solve my problem, I figured that I'd post my specific problem.

Here is a minimal example to illustrate this issue:

\documentclass{beamer}
\setbeameroption{show notes}
\begin{document}
\begin{frame}<1-2>[label=myframe]{Frame Title}
  \note<1>{Some notes on the first point.}
  \note<2>{Some notes on the second point.}
  \begin{itemize}
  \item<alert@1> First point.
  \item<alert@2> Second point.
  \item<alert@3> Third point. %optional
  \end{itemize}
\end{frame}
\appendix
\begin{frame}{Appendix}
  Some more elaboration.
\end{frame}
\againframe<3>{myframe}
\end{document}

This example is compilable, but LaTeX tells me there are multiply defined labels. The labels in question are myframe, myframe<1> and myframe<2>. I conjecture this is due to the fact that when a note page is created, the note page also "inherits" the label of the main frame, thus creating such problem. If so, I guess we could somehow patch the note page mechanism in beamer such that LaTeX would stop emit such warnings.

Anyone has any solutions?

Best Answer

Understanding why the problem occurs and how to potentially fix it is a bit TeXnical I'm afraid.

Diagnosing causes of the problem:

  • Disabling notes eliminates the issue.
  • Redefining \insertslideintonotes to do nothing eliminates the issue: \renewcommand{\insertslideintonotes}[1]{}.
  • Using any form of \label (even \label<1>) in a slide with notes causes the issue, not just using the label=name option to frames (the latter internally uses \label anyway).

  • Implementation of \insertslideintonotes in beamer:

    beamer puts the contents of each slide into a box register called \beamer@framebox, and copies the box register into \beamer@frameboxcopy. The latter is used for the mini version of the slide shown in the notes pages (via \insertslideintonotes). Label commands are also stored in those boxes in the form of 'whatsit' \write nodes, and so are written again when the box is copied.

Why multiply defined labels can be problematic:

  • Multiply defined labels are not always consistent. The default behaviour in LaTeX is to use the last defined label, rather than ignoring later redefinitions of the same label. This is not the desired behaviour in the case of beamer because the label will then refer to notes slides instead of the main slide (as notes slides always come after the main slide). The following example illustrates this (the reference in the last frame is wrong):

    \documentclass{beamer}
    \setbeameroption{show notes}
    
    \begin{document}
    
    \begin{frame}<1-2>[label=myframe]{Frame Title}
      \note<1>{Some notes on the first point.}
      \note<2>{Some notes on the second point.}
      \begin{itemize}
      \item<alert@1> First point.
      \item<alert@2> Second point.
      \item<alert@3> Third point. %optional
      \end{itemize}
    \end{frame}
    \appendix
    \begin{frame}{Appendix}
      Some more elaboration.
    
      I think \texttt{myframe} starts on page \getpagerefnumber{myframe}.
    \end{frame}
    \end{document}
    

Solutions

  • I asked a question about removing or deactivating such nodes in this question, and Stephan Lehmke's solution led me to the following patch. The idea is that by editing the box to use \leaders, TeX will ignore the \write whatsits. I will try to get the beamer maintainers to consider it for inclusion in the beamer core:

    Patch code:

    \usepackage{etoolbox}
    \makeatletter
    \patchcmd\beamer@framenotesend{\global\setbox\beamer@frameboxcopy=\copy\beamer@framebox}{%
    \global\setbox\beamer@frameboxcopy=\copy\beamer@framebox
    \global\setbox\beamer@frameboxcopy=\hbox{\leaders\copy\beamer@frameboxcopy\hskip\wd\beamer@frameboxcopy}%from Stephan Lehmke's comment on https://tex.stackexchange.com/q/82250/17427
    }{}{\showtokens{failed to patch \beamer@framenotesend}}
    \makeatother
    

    Patched MWE (note that the pdfTeX warning (dest) messages are another outstanding issue in beamer):

    \documentclass{beamer}
    \setbeameroption{show notes}
    
    \usepackage{etoolbox}
    \makeatletter
    \patchcmd\beamer@framenotesend{\global\setbox\beamer@frameboxcopy=\copy\beamer@framebox}{%
    \global\setbox\beamer@frameboxcopy=\copy\beamer@framebox
    \global\setbox\beamer@frameboxcopy=\hbox{\leaders\copy\beamer@frameboxcopy\hskip\wd\beamer@frameboxcopy}%from Stephan Lehmke's comment on https://tex.stackexchange.com/q/82250/17427
    }{}{\showtokens{failed to patch \beamer@framenotesend}}
    \makeatother
    
    \begin{document}
    
    \begin{frame}<1-2>[label=myframe]{Frame Title}
      \note<1>{Some notes on the first point.}
      \note<2>{Some notes on the second point.}
      \begin{itemize}
      \item<alert@1> First point.
      \item<alert@2> Second point.
      \item<alert@3> Third point. %optional
      \end{itemize}
    \end{frame}
    \appendix
    \begin{frame}{Appendix}
      Some more elaboration.
    
      I think \texttt{myframe} starts on page \getpagerefnumber{myframe}.
    \end{frame}
    \againframe<3>{myframe}
    \end{document}
    
  • The alternative implementation that beamer could take would be to reprocess the content of the whole frame again when calling \insertslideintonotes, but which might have other unwanted side-effects in some circumstances, and so this should only be provided as an option to people who know what they are doing, instead of changing default behaviour! I don't think this would be an easy job either.

  • You could also use the following patch in the preamble to only save the first \label, and hope everything will be alright.

    % keep only the first definition of a given label, in contrast to the default LaTeX behaviour (and compile twice to see the difference!)
    \makeatletter
    \def\@newl@bel#1#2#3{{%
      \@ifundefined{#1@#2}%
        {\global\@namedef{#1@#2}{#3}}% moved this line from always being executed into the 'true' case for \@ifundefined.
        {\gdef \@multiplelabels {%
           \@latex@warning@no@line{There were multiply-defined labels. Later redefinitions were ignored}}%
         \@latex@warning@no@line{Label `#2' multiply defined. Ignoring later redefinitions}}%
      }}
    \makeatother