Biblatex gobbles punctuation after undefined references

Fixed in version 3.8 of biblatex (#630)

I had a bit of time on my hands to investigate this.

In a \cite-like command the first time the citation list is processed with \blx@citeadd, this happens in \blx@citeloop. That command distinguishes citations that were found in the .bib file and those that weren't (i.e. are undefined). The citations that were found are saved in a macro for further processing, the keys of those that weren't found are written out immediately in bold. Then the defined citations are passed on to \blx@citeprint. The command \blx@postcode that does the postpunct stuff - and a little bit more if required - is only called in \blx@citeprint when the last item has been processed.

If we have only undefined citations in our cite command, we never call \blx@postcode since the chain of macros is only executed with the list of defined citations, and not at all if this list is empty.

So we need to make \blx@citeloop call \blx@postcode directly in case there are no defined citations. It turns out that due to the nature of the additional code that \blx@postcode might contain it is not safe to execute there. We need to save the postpunct in a new command and use that instead.

My solution is to split the postpunct part from \blx@postcode into a new \blx@postpunct@saved (sadly the name \blx@postpunct was already taken, but suggestions for a better name are gladly accepted). This new macro can then be called in \blx@citeloop if there are no defined citations and otherwise together with \blx@postcode in \blx@citeprint.

The necessary modifications are not very copious, but the nature of the changed macros does not allow for a short MWE. The necessary changes can be found in the pull request https://github.com/plk/biblatex/pull/630; it has been merged and the fix is included in biblatex v3.8.

Now

\listfiles
\documentclass[american]{article}
\usepackage{babel}
\usepackage[style = authortitle]{biblatex}
\addbibresource{biblatex-examples.bib}

\begin{document}

\textcite{UNDEFINED}A

\textcite{fghgvjh}:

\textcite{UNDEFINED}:

\textcite{aksin}:

\textcite{UNDEFINED,aksin}:

\cite{UNDEFINED,aksin}.

\textcite{aksin,UNDEFINED,gundf}:

\textcite{UNDEFINED,FLUNDF}A

\textcite{UNDEFINED,FLUNDF}:

\textcite{aksin,sigfridsson}:

\cite[14]{UNDEFINED,aksin}:

\cite[14]{UNDEFINED,aksin}A

\end{document}

gives

MWE output


What I decided on in the end is to patch \blx@citeadd. I am not sure if this is the best macro to patch. It seems the "gobbled" punctuation is kept in \abx@field@postpunct.

\documentclass{article}
\usepackage{xpatch}
\usepackage[style = authoryear]{biblatex}
\addbibresource{biblatex-examples.bib}

\makeatletter
\xpatchcmd{\blx@citeadd}{%
    \expandafter\abx@missing\expandafter{\blx@realkey}%
}{%
    \expandafter\abx@missing\expandafter{\blx@realkey}%
    \ifundef{\abx@field@postpunct}{}{\abx@field@postpunct}%
}{}{}%
\makeatother

\begin{document}

\textcite{UNDEFINED}A

\textcite{UNDEFINED}:

\textcite{aksin}:

\end{document}