Hello all (especially Joseph, who might have to deal with this), Based on the discussion at http://tex.stackexchange.com/questions/179180 there seems to be a problem with the definition of \__keys_bool_set:Nn. Namely, it is not obvious that the following code should fail \keys_define:nn { mymodule } { key-1 .choice: , key-1 / choice-a .bool_set:N = \l_mymodule_choice_a_bool, key-1 / choice-b .bool_set:N = \l_mymodule_choice_b_bool } \keys_set:nn { mymodule } { key-1 = choice-a } and yet it hangs because \__keys_bool_set:Nn actually creates a choice key with the choices 'true' and 'false' under the hood. I feel it would be more natural if the code above behaved in the same way as the following: \keys_define:nn { mymodule } { key-2 .bool_set:N = \l_mymodule_choice_a_bool } \keys_set:nn { mymodule } { key-2 } In other words, the code that now hangs should just be setting the boolean to 'true'. If \__keys_bool_set:Nn and \__keys_bool_set_inverse:Nn were redefined along the lines of the code below, we'd get that result. \cs_new_protected:Npn \__keys_bool_set:Nn #1#2 { \bool_if_exist:NF #1 { \bool_new:N #1 } \__keys_cmd_set:nn { \l_keys_path_tl } { \str_case_x:nnF { \l_keys_value_tl } { { true } { \use:c { bool_ #2 set_true:N } #1 } { false } { \use:c { bool_ #2 set_false:N } #1 } } { \cs_if_exist:cTF { \c__keys_code_root_tl \l_keys_path_tl / \l_keys_value_tl } { \use:c { bool_ #2 set_true:N } #1 } { \__msg_kernel_error:nnx { kernel } { boolean-values-only } { \l_keys_key_tl } } } } \__keys_default_set:n { true } } \cs_new_protected:Npn \__keys_bool_set_inverse:Nn #1#2 { \bool_if_exist:NF #1 { \bool_new:N #1 } \__keys_cmd_set:nn { \l_keys_path_tl } { \str_case_x:nnF { \l_keys_value_tl } { { true } { \use:c { bool_ #2 set_false:N } #1 } { false } { \use:c { bool_ #2 set_true:N } #1 } } { \cs_if_exist:cTF { \c__keys_code_root_tl \l_keys_path_tl / \l_keys_value_tl } { \use:c { bool_ #2 set_false:N } #1 } { \__msg_kernel_error:nnx { kernel } { boolean-values-only } { \l_keys_key_tl } } } } \__keys_default_set:n { true } } Finally, and a lower priority: it might also be useful to add the properties .bool_set_true:N and .bool_set_false:N as well. For example, they could work like this: \cs_new_protected:Npn \__keys_bool_set_true:Nn #1#2 { \bool_if_exist:NF #1 { \bool_new:N #1 } \__keys_cmd_set:nn { \l_keys_path_tl } { \use:c { bool_ #2 set_true:N } #1 } \__keys_value_requirement:n { forbidden } } \cs_generate_variant:Nn \__keys_bool_set_true:Nn { c } \cs_new_protected:Npn \__keys_bool_set_false:Nn #1#2 { \bool_if_exist:NF #1 { \bool_new:N #1 } \__keys_cmd_set:nn { \l_keys_path_tl } { \use:c { bool_ #2 set_false:N } #1 } \__keys_value_requirement:n { forbidden } } \cs_generate_variant:Nn \__keys_bool_set_false:Nn { c } \cs_new_protected:cpn { \c__keys_props_root_tl .bool_set_true:N } #1 { \__keys_bool_set_true:Nn #1 { } } \cs_new_protected:cpn { \c__keys_props_root_tl .bool_set_true:c } #1 { \__keys_bool_set_true:cn {#1} { } } \cs_new_protected:cpn { \c__keys_props_root_tl .bool_gset_true:N } #1 { \__keys_bool_set_true:Nn #1 { g } } \cs_new_protected:cpn { \c__keys_props_root_tl .bool_gset_true:c } #1 { \__keys_bool_set_true:cn {#1} { g } } \cs_new_protected:cpn { \c__keys_props_root_tl .bool_set_false:N } #1 { \__keys_bool_set_false:Nn #1 { } } \cs_new_protected:cpn { \c__keys_props_root_tl .bool_set_false:c } #1 { \__keys_bool_set_false:cn {#1} { } } \cs_new_protected:cpn { \c__keys_props_root_tl .bool_gset_false:N } #1 { \__keys_bool_set_false:Nn #1 { g } } \cs_new_protected:cpn { \c__keys_props_root_tl .bool_gset_false:c } #1 { \__keys_bool_set_false:cn {#1} { g } } All the best, Jura Pintar