Diagnose Permanent ‘Label(s) May Have Changed’ Warning – Cross-Referencing

cross-referencingwarnings

I'm getting the following warning:

LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.

The problem is, it doesn't go away after rerunning (any number of times).

The document in question is over 200 pages long and includes about 30 packages, so it's not really feasible for me to provide a minimal example. But I know my own code pretty well. I can probably fix it if I knew a bit more about the problem. So I want to ask some general questions:

  • How does the "labels changed; rerun" mechanism work, anyway?
  • Is there a common culprit responsible for this problem?
  • How would someone generally go about diagnosing it?

I've read the following question:

But I'm not using the elsarticle or acronym packages, so the accepted answer didn't apply to me.


More info: As suggested, I did a kind of 'commenting out' binary search. (By the way, if LaTeX knows that labels may have changed, why can't it tell me which labels?)

Anyway, I seemed to track down the problem to a specific figure. When I compile only chapters 1 to 3, removing that figure also removes the warning. However, if I once again include all chapters, removing that figure isn't enough. So I guess there are other problem locations. But I don't have time to search chapters 4 to 9 right now…

I can also tell you this: I have a tmp directory where LaTeX and friends dump all temporary files. And between two compilations, the relevant content of this directory does not change at all. That is to say, diff -r tells me that the only changes are some timestamps and the .pdf file. In particular: all .aux files are identical.

Best Answer

(By the way, if LaTeX knows that labels may have changed, why can't it tell me which labels?)

The following document will give the re-run error message each time.

\documentclass{article}

\makeatletter


% \def\@testdef #1#2#3{%
%   \def\reserved@a{#3}\expandafter \ifx \csname #1@#2\endcsname
%  \reserved@a  \else
% \typeout{^^Jlabel #2 changed:^^J%
% \meaning\reserved@a^^J%
% \expandafter\meaning\csname #1@#2\endcsname^^J}%
% \@tempswatrue \fi}


\begin{document}
\providecommand\r@foo{{1}{1}}
\edef\@currentlabel{.\expandafter\@firstoftwo\r@foo}
\label{foo}
a

\end{document}

produces a log

LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.

If you uncomment the block in the preamble you get an additional diagnostic telling you which label has changed, and the old and new definition:

label foo changed:
macro:->{............1}{1}
macro:->{...........1}{1}

)

LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.