latex3
JouleV
```
% arara: pdflatex
\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\msg_new:nnn { foo } { bar } { Some~text~about~#1~blah~blah }
\msg_info:nnn { foo } { bar } { \foo_bar }
\msg_info:nnn { foo } { bar } { something~which~is~not~a~cs }
\ExplSyntaxOff
\end{document}
```

```
% Bad
Package foo Info: Some text about \foo_bar  blah blah

% Good
Package foo Info: Some text about something which is not a cs blah blah

% Expected
Package foo Info: Some text about \foo_bar blah blah
```

Did I miss something in the manual, or is this a bug in `expl3`?
Top Answer
Phelype Oleinik
This is not a category code issue, rather the timing of tokenisation. You'd see this same issue in this code:
```tex
\def\test#1{\immediate\write16{\unexpanded{A #1 B}}}
\test{foobar}
\test{\foobar}
```

First, when `\test` is defined, it contains the tokens (I used `·` to separate them):
```tex
\immediate·\write·1·6·{·\unexpanded·{·A· ·#1· ·B·}·}
```
Everything looks normal so far (except that `#1` is not one single thing, but the two tokens `macro parameter character #` and `the character 1`, but for the sake of this example, that doesn't change anything). Notice that `A· ·#1· ·B` contains the 5 tokens: `the letter A`, `blank space ​ ​`, `#1`, `blank space ​ ​`, and `the letter B`.

When you use the macro `\test` with either `foobar` or `\foobar`, TeX replaces `#1` by the argument and prints that. The difference appears because when TeX writes control sequence tokens it _prints_ an additional space after it, so you get `A \foobar ​ B`, but that's only for _printing_ !  The token representation of that is still `A· ·\foobar · ·B`, which is the same 5 tokens you started with.

Your workaround with `\string` works because `\string\foobar` turns a control sequence token into the string of _character_ tokens `\·f·o·o·b·a·r`, which is not much different from `x·f·o·o·b·a·r`.
Answer #2
JouleV
Oh, as it turns out, this has something to do with category codes[^1] again...

```
% arara: pdflatex
\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\msg_new:nnn { foo } { bar } { Some~text~about~#1~blah~blah }
\cs_generate_variant:Nn \msg_info:nnn { nnx }
\msg_info:nnx { foo } { bar } { \token_to_str:N \foo_bar }
\msg_info:nnn { foo } { bar } { something~which~is~not~a~cs }
\ExplSyntaxOff
\end{document}
```

```
% Both good:
Package foo Info: Some text about \foo_bar blah blah

Package foo Info: Some text about something which is not a cs blah blah
```

However I still don't know how an extra space is added, but no warnings or errors are issued at all...

[^1]: I don't use the word "catcode" because I fear the cats won't give me permission to do so :)

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.