Hyperlink prints OK but jumps to wrong target

cleverefcross-referencingcrossreftoolshyperlinkhyperref

When I use pdflatex to process a book-length document, in chapter 6 a couple of isolated links to theorem-like environments in that same chapter appear printed correctly in the pdf output, but clicking those links takes one to the same-numbered item in a different chapter!

Specifically, the link whose text is "Example 6.9" jumps to Example 1.9, and the link whose text is "Proposition 6.12" jumps to "Proposition 6.12".

The labels of the wrongly jumped-to targets are definitely entirely different from the labels of the intended targets.

What could be wrong?

Alas, so far I cannot produce a MWE. The preamble is split over a dozen separate files.

To help in the diagnosis, below are:

  • extracts from the source where the relevant labels are defined and where they are cross-referenced;

  • corresponding entries in the .aux files; and

  • extracted sections of the preamble files where theorem-like environments are defined and cross-referencing (hyperref, cleveref, crossreftools, etc.) is set up.

Wrong jump #1 – source in chapter 6 correctly prints in pdf as "Example 6.9":

Show that the quotient space $\mathbb{R} /!/ \mathbb{Q}$ of \cref{ex:non-cr-quot-cr} is in fact not a Hausdorff space.

Wrong jump #1 — target, again in chapter 6, is the following (but link jumps to 1.9 instead):

Show that the quotient space $\mathbb{R} /\!/ \mathbb{Q}$ 
of \cref{ex:non-cr-quot-cr} is in fact not a Hausdorff space.

Wrong jump #1 — target, again in chapter 6, is the following (but link jumps to 1.9 instead):

\begin{example}
\label{ex:non-cr-quot-cr}
\index{line with two origins!separation properties@and separation properties}%
\index{line with two origins!quotient space@as quotient space}

The line with two origins ....
\end{example}

Wrong jump #1 — .aux extract:

\@@wrindexm@m{topology2}{Cartesian sum!completely regular space@and completely regular space|hyperpage}{589}
\@writefile{loe}{\contentsline {example}{\ifthmt@listswap \MakeUppercase  {e}xample~6.9\else \numberline {6.9}\MakeUppercase  {e}xample\fi }{590}{example.9}\protected@file@percent }
\newlabel{ex:non-cr-quot-cr}{{\M@TitleReference {6.9}{Completely regular spaces}}{590}{}{example.9}{}}
\newlabel{ex:non-cr-quot-cr@cref}{{[example][9][]6.9}{[1][590][]590}}
\@writefile{lla}{\contentsline {section}{\numberline {\crtrefnumber{ex:non-cr-quot-cr}}ex:non-cr-quot-cr}{590}{example.9}\protected@file@percent }

Wrong jump #2 — source in chapter 6 is correctly printed in pdf as "Proposition 6.12":

Prove \cref{prop:closed-subspace-of-normal}: a closed subspace 
of a normal space is itself normal.

Wrong jump #2 — target, again in chapter 6, is the following (but link jumps instead to 2.12):

\begin{proposition}
\label{prop:closed-subspace-of-normal}    
A closed subspace of a normal space is itself normal.    
\end{proposition}

Wrong jump #2 — .aux extract:

\@@wrindexm@m{topology2}{subspace!normal space@of normal space|(hyperpage}{591}
\@writefile{loe}{\contentsline {proposition}{\numberline {6.12}Proposition}{591}{proposition.12}\protected@file@percent }
\newlabel{prop:closed-subspace-of-normal}{{\M@TitleReference {6.12}{Normal spaces}}{591}{}{proposition.12}{}}
\newlabel{prop:closed-subspace-of-normal@cref}{{[proposition][12][]6.12}{[1][591][]591}}
\@writefile{lla}{\contentsline {section}{\numberline {\crtrefnumber{prop:closed-subspace-of-normal}}prop:closed-subspace-of-normal}{591}{proposition.12}\protected@file@percent }

From the preamble:

%% MATH & THEOREMS
\usepackage{amsmath}
\usepackage{mathtools}
\usepackage{amsthm} 
\RequirePackage{thmtools}

\swapnumbers % Invert numbers/labels

\newcommand{\thmlikefont}{\sffamily\bfseries}

\declaretheoremstyle[
  headfont=\thmlikefont,
  headpunct={\thmlikefont.},
  postheadspace=0.5em,
  notefont=\thmlikefont,
  headformat=\NAME\NUMBER\let\thmt@space\@empty\NOTE,
  bodyfont=\mdseries,
  spaceabove=12pt,spacebelow=12pt,
  hidealllines=true,
  innerleftmargin=8pt,innerrightmargin=8pt,
  postheadhook={%
    \ifx\@empty\thmt@shortoptarg
      \renewcommand\addcontentsline[3]{}
    \fi}
]{thmstyle}
\theoremstyle{thmstyle}

\declaretheorem[name=Theorem,numberwithin=chapter]{theorem}
\newtheorem{proposition}[theorem]{Proposition}

\declaretheoremstyle[
  headfont= \thmlikefont,
  headpunct={\thmlikefont.},
  postheadspace=0.5em,
  notefont=\thmlikefont,
  bodyfont=\normalfont,
  spaceabove=12pt,spacebelow=12pt
]{defstyle}
\declaretheorem[
  style=defstyle,
  numberlike=theorem,
  preheadhook=\renewcommand{\qedsymbol}{$\myDiamond$}\pushQED{\qed},
  postfoothook=\popQED
  ]
{example}

%%  CROSS-REFERENCING
\RequirePackage{xurl}

\usepackage{datetime2} % to satisfy the "\today" in \hypersetup
\DTMusemodule{english}{en-US}

\RequirePackage{hyperxmp} % to add metadata info into pdf
\usepackage{hyperref}
\hypersetup{
  unicode,
  pdfapart=2, pdfaconformance=u,
  bookmarksnumbered,bookmarksopen=true,bookmarksopenlevel=3,
  breaklinks=true,
  colorlinks, citecolor=red, linkcolor=blue, urlcolor=blue,
  linktocpage=true,linktoc=all,
  pdftitle={Topology, Second Edition},
  % ...(other entries re author, publication, etc.)...
   pdfproducer=pdfTeX-1.40.23, %why needed ????????????
}

% Allow link to page with label -- patch by Martin Scharrer
% cf. https://tex.stackexchange.com/a/19416/9237
\let\orig@Hy@EveryPageAnchor\Hy@EveryPageAnchor
\def\Hy@EveryPageAnchor{%
    \begingroup
    \hypersetup{pdfview=Fit}%
    \orig@Hy@EveryPageAnchor
    \endgroup
}
% My commands to use that
% Usage: \crefpagetext{text-to-appar-in-link}{lbl} with usual \label{lbl} for target.
\newcommand{\crefpagetext}[2]{\hyperlink{page.\getpagerefnumber{#2}}{#1} on \cpageref{#2}}
\WithSuffix\newcommand\crefpagetext*[2]{\hyperlink{page.\getpagerefnumber{#2}}{#1}}

\AtBeginDocument{\addtocontents{toc}{\protect\hypersetup{hidelinks}}}

%% Allow ref to section n, not section m.n
% From "trickier version" by Christian Hupfer
% https://tex.stackexchange.com/a/383608/13492
\let\@xp\expandafter
%
% Stripping the dot from the 1.2 -like reference
\def\@@stripdot#1.#2\@nil{#2}
%
% Stripping the memoir stuff from the reference, i.e. \M@TitleReference {1.2}{FOO} and handing #1 (1.2) over to the \@@stripdot macro
\def\@stripdot\M@TitleReference #1#2\@nil{\@@stripdot#1\@nil}
%
%Macro, second level of expansion
\newcommand{\stripdot}[1]{%
  \@xp\@stripdot#1\@nil
}
\newcommand{\crefsec}[1]{%
  % Expand the argument first
  \IfRefUndefinedExpandable{#1}{%
    % Do nothing if #1 is not defined
  }{%
    \hyperlink{\getrefbykeydefault{#1}{anchor}{}}{\@xp\stripdot\@xp{\getrefnumber{#1}}}%
  }%
}

\RequirePackage[nameinlink,noabbrev,capitalize]{cleveref}
\RequirePackage{crossreftools}
% Fix to crossreftools
% https://tex.stackexchange.com/a/512175/13492
\renewcommand{\@@crtextr@ct@ref}[2]{%
  \expandafter\@@@crtextr@ct@ref\expandafter{\detokenize{#2}}{#1}%
}
\newcommand{\@@@crtextr@ct@ref}[2]{%
  \expandafter\ifx\csname r@#1\endcsname\relax
  \crt@refundefined%
  \else
  \expandafter\expandafter\csname crt@ref@splitter@#2\endcsname\csname r@#1\endcsname%
  \fi
}

\crefname{proposition}{Proposition}{Propositions}
\Crefname{proposition}{Proposition}{Propositions}
\crefname{example}{Example}{Examples}
\Crefname{example}{Example}{Examples}

% Added 2020-03-17
% From https://tex.stackexchange.com/questions/1230/reference-name-of-description-list-item-in-latex
\def\namedlabel#1#2{\begingroup
    #2%
    \def\@currentlabel{#2}%
    \phantomsection\label{#1}\endgroup
}

Many other packages are loaded, including babel, but I think the ones shown in the preceding preamble extract are the relevant ones.

Added 2022-04-28 attempted fixes

I tried suggestions from https://tex.stackexchange.com/a/642073/13492, but without success:

  1. Replacing the \newtheorem declarations to corresponding ones from thmtools. Thus I used the following, which does not eliminate the wrong jumps:

    \declaretheorem[name=Theorem, style=thmstyle, numberwithin=chapter]{theorem}
    
    \declaretheorem[name=Proposition, style=thmstyle, numberlike=theorem]{proposition}
    \declaretheorem[name=Definition, style=defstyle, numberlike=theorem]{definition}
    
  2. I was unable to match the git diff file for aliascntr.dtx with the existing version of that aliascntr.dtx in TeXLive 2022.

  3. In addition to the changes indicated in #1, I added the \counterwithin statements from 3:

     \counterwithin{proposition}{chapter}
     \counterwithin{example}{chapter}
    

Now the jumps seem to be correct!

Given the size and complexity of the book and its source files, I need to continue sampling link jumps to verify that all is now well.

Best Answer

Looking at the aux file output, I have a suspicion that you are running into the same (or at least very similar) bug that I diagnosed in this previous answer.

While a patch has been checked into the Git repo, a release has not been made onto CTAN (the current version is dated August 2020). If I were you I would try a few different things:

  1. First try to see changing everything to thmtools syntax helps. I am pessimistic that this will solve your problem.
  2. If you feel confident at mucking about with package internals: make a copy of the aliasctr.sty file from thmtools into your working directory, and apply the changes indicated in the Git commit fixing this bug.
  3. Alternatively, if you are not confident mucking about, I would suggest trying the following workaround:
    • Step 1: change the declaration of proposition to thmtools syntax. (This is important, this workaround depends on how \declaretheorem works and will fail with \newtheorem.)
    • Step 2: add, after declaring proposition and example, the following two lines (for an explanation of why this may work, see the first link to my diagnoses above)
    \counterwithin{proposition}{chapter}
    \counterwithin{example}{chapter}
    
  4. Alternatively: you can also rewrite everything using completely just amsthm syntax and not thmtools. The syntax for amsthm is certainly clunkier, but the code does work with cleveref. (I've generally avoided using thmtools myself now.)