I defined a macro that typesets a technical name using math symbols, in my example $\alpha$-thingy. When used in a \section, \hyperref would complain that it cannot use the symbol to compose the string in the pdf's index. So I defined the macro so it uses \texorpdfstring to provide the alternate text-only form alpha-thingy for the index. This works very well unless the macro has an optional argument. This MWE shows the issue:




  \section{Example \working}
  Hello \working.
  \section{Example \nonworking}
  Hello \nonworking.
  \section{Example \nonworking[thingy]}
  Hello \nonworking[thingy].

In the log I get two warnings:

W: mwe.tex:11 Token not allowed in a PDF string (PDFDocEncoding):(hyperref) removing `\nonworking'
W: mwe.tex:13 Token not allowed in a PDF string (PDFDocEncoding):(hyperref) removing `\nonworking'

How can I make hyperref happy without having to use \texorpdfstring directly in the \section's argument each time?

1 Answer 1


You cannot use optional arguments for bookmarks, because LaTeX's implementation uses \futurelet, which is not expandable. Bookmarks strings are not typeset by TeX, only converted to a string.

Since the macro with the optional argument does not have a following mandatory argument, there is no way detecting the optional argument using a macro-based approach.

The follwing example defines \test with an optional and a mandatory argument. The mandatory argument is not used, thus this is more an artificial example to show the way:


\bookmarksetup{numbered, open}



  \section{Example \working}
  Hello \working.
  \section{Example \test{}}
  Hello \test{}.
  \section{Example \test[thingy]{}}
  Hello \test[thingy]{}.





  • Package bookmark improves the bookmark handling and adds some features.
  • Option pdfencoding=auto uses Unicode for the bookmarks and PDFDocEncoding, if Unicode is not necessary for the bookmark string.
  • The basic trick is \def\test#1#. This puts the optional argument including the square brackets inside #1, if it is given. If the mandatory argument is directly following \test, then #1 is empty, which is tested by \ifx\\#1\\.
  • 1
    wow, so much black magic...could you explain where does the second # in \def\test#1# come from?
    – Bordaigorl
    Feb 7, 2015 at 23:07
  • @Bordaigorl The second # is a special case. At the end of the parameter text, it matches/expects an opening curly brace. Feb 7, 2015 at 23:29
  • just two more questions: 1) where can I read more about this use of #? 2) suppose I do not need to support the first use of \nonworkin in my MWE but I can assume I always specify the optional argument when using the macro as a \section's argument. Is there a less obscure way to handle that?
    – Bordaigorl
    Feb 11, 2015 at 11:54
  • Couldn't one redefine futurelet in this context since the very restrictions that are causing problems here would presumably make it easier to fake futurelet in some way no? But the more I think about it the more I'm unsure. Nov 6, 2020 at 23:23
  • @PeterGerdes \futurelet is a non-expandable primitive command (like \let, \def, \edef) that cannot be simulated by macros. Nov 7, 2020 at 20:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .