[Tex/LaTex] \relax undefined in tocloft \cftchapaftersnum

errorstable of contentstocloft

I found this error while try to compile latex document in my new machine:

! LaTeX Error: \relax undefined.
l.35 \renewcommand
            {\cftchapaftersnum}{.}

It didn't appear in my previous machine. I've just installed Miktex 2.9 there with basic standard
This is my very minimum working example. Hope it is clear enough. :

\documentclass[12pt, a4paper, onecolumn, oneside, final]{report}
\usepackage[titles]{tocloft}

\setlength{\cftaftertoctitle}
\renewcommand{\cftchapaftersnum}{.}
\renewcommand{\cftdotsep}{1}
\renewcommand{\cftchapdotsep}{1}
\renewcommand{\cftchapleader}{\cftdotfill{\cftchapdotsep}}

\addtocontents{toc}{\protect\renewcommand{\protect\cftchapfont}{}}
\addtocontents{toc}{\protect\renewcommand{\protect\cftchappagefont}{\itshape}}
\addtocontents{toc}{\protect\renewcommand{\protect\cftchappagefont}{}}
\addtocontents{toc}{\protect\setlength{\cftbeforechapskip}{0pt}}
.
.

\begin{document}
.
.
\end{document}

At first, looks like just forget to install one single package. But, after quick googling by \relax undefined keyword, I've learned that it is not as simple as I was thinking. Is it really those complicated, or indeed just one single package missing?

Best Answer

The error message you get is indeed puzzling: forgetting the second argument for \setlength most of the times results in

! Missing number, treated as zero.

or, if a number happens to follow, in

! Illegal unit of measure (pt inserted).

Let's see why you get the mysterious

! LaTeX Error: \relax undefined.

error message.

First of all, as already observed in the comments, you're forgetting the second argument to \setlength, but TeX doesn't know it and takes as argument the following token or braced group. In this case it finds \renewcommand, so what you get is

\setlength{\cftaftertoctitle}\renewcommand{\cftchapaftersnum}{.}

(the space coming from the end-of-line is ignored because TeX is looking for a normal argument).

Now TeX expands \setlength using its definition:

% latex.ltx, line 1874:
\def\setlength#1#2{#1#2\relax}

so you get

\cftaftertoctitle\renewcommand\relax{\cftchapaftersnum}{.}

Now, \cftaftertoctitle is NOT a parameter, but a macro which by default expands to nothing. Hence TeX is confronted with

\renewcommand\relax{\cftchapaftersnum}{.}

which is illegal, because any command equivalent to \relax is undefined as far as LaTeX is concerned.

In conclusion, your code is flawed in two ways:

  1. You're missing an argument for \setlength;
  2. You're trying to set a macro to a length, which is illegal.

Indeed, also \setlength{\cftaftertoctitle}{2pt} would raise another puzzling error:

! LaTeX Error: Missing \begin{document}.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.4 \setlength{\cftaftertoctitle}{2pt}

Exercise: find out why.