# Strange behaviour in l3keys

Consider the following code which uses \keys_set_known:nnN:

\documentclass{article}
\usepackage{expl3}

\ExplSyntaxOn
\keys_define:nn {empty_module} {}
\keys_define:nn {module1}
{key1 .code:n = {\keys_set:nn {empty_module} {a_key}}}
\keys_set_known:nnN {module1} {key1} \l_tmpa_clist
\clist_show:N \l_tmpa_clist
\ExplSyntaxOff

\begin{document}
\end{document}


When executing \keys_set_known:nnN {module1} {key1} \l_tmpa_clist, the key key1 is found in module1 and, then, the corresponding code \keys_set:nn {empty_module} {a_key} is executed. However, there is no key a_key in empty_module and I would expect an error. But, instead, the key a_key is transferred to \l_tmpa_clist as we can see with the clist_show:N.

I would like to know whether this is a bug or the expected behaviour as suggested (maybe) by interface3.pdf:

Use of \keys_set_known:nnN can be nested, with the correct residual keyval list returned at each stage.

I'm not sure if this can be called expected behaviour, but it's how the function is implemented.

From expl3-code.tex, the definition of \keys_set_known:nnN is (plus wrapper code and a few more things):

\keys_set_known:nn {#2} {#3}
\tl_set:Nx #4 { \exp_not:o { \l__keys_unused_clist } }


where #2 is the module, #3 is the key-value list, and #4 is the tl var to store the unused keys. The function is the same as \keys_set_known:nn but it saves the contents of \l__keys_unused_clist in #4. So let's go for \keys_set_known:nn.

The code for \keys_set_known:nn now does:

\bool_set_true:N \l__keys_only_known_bool
\keys_set:nn {#1} {#2}
\bool_set_false:N \l__keys_only_known_bool


which is basically \keys_set:nn with a different behaviour for unknown keys.

(somewhere in the code of l3keys you can see:

\bool_if:NTF \l__keys_only_known_bool
{ \__keys_store_unused: }
{
\cs_if_exist:cTF
{ \c__keys_inherit_root_tl \__keys_parent:o \l_keys_path_tl }
{ \__keys_execute_inherit: }
{ \__keys_execute_unknown: }
}


which either stores the unknown key in \l__keys_unused_clist or tries to do another thing with the key, depending of the value of \l__keys_only_known_bool).

So, the bottom-line is: when you call \keys_set_known:nnN you temporarily disable the unknown key-checking code, so the error you expected to see doesn't appear. Instead, as an unknown key is found, the \__keys_store_unused: is called for a_key and it is stored in the unused list at the end.

This is now fixed in the development code: see https://github.com/latex3/latex3/issues/526. The next release will take place within a few days and will address this and other l3keys issues.