Por que \msg_fatal: mostra um erro aparentemente não relacionado?

Por que \msg_fatal: mostra um erro aparentemente não relacionado?
\documentclass{article}
\usepackage{expl3}
\usepackage{everypage}

\ExplSyntaxOn
\AddEverypageHook { \sean_test: }

\msg_new:nnnn { test } { message }
  { this ~ is ~ a ~ rubbish ~ message }
  { it's ~ a ~ minimal ~ example }

\cs_new_protected:Npn \sean_test:
  {
    \typeout{++before++}
    \msg_fatal:nn { test } { message }
    \typeout{++after++}
  }

\ExplSyntaxOff

\usepackage{mwe}
\begin{document}
\lipsum[1-1000]
\end{document}

Estou bastante surpreso por ter conseguido fazer um exemplo mínimo disso, mas o texto acima produzirá (muitas cópias de)

++after++
[26]
++before++

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! Fatal test error: "message"
! 
! this is a rubbish message
! 
! See the test documentation for further information.
! 
! For immediate help type H <return>.
!...............................................  

l.23 \lipsum[1-1000]

! You can't use `\end' in internal vertical mode.
\__msg_fatal_code:nnnnnn ...l_text_tl }\tex_end:D 

l.23 \lipsum[1-1000]

++after++
[27]
++before++

O que há com esse negócio?

! You can't use `\end' in internal vertical mode.
\__msg_fatal_code:nnnnnn ...l_text_tl }\tex_end:D 

Tentei apresentar ambos \leavevmode\tex_end:De \clearpage\tex_end:Dsem efeito.

Responder1

Você não pode morrer lá.

O gancho que você está usando é presumivelmente executado dentro da rotina de saída que é sempre o modo vertical interno (como você não está, por definição, na lista vertical principal), então você não pode parar por aí, você precisa sair da rotina de saída primeiro.


É possível fazer algo para tentar morrer fora da caixa interna,Morra outro dia(citado Paulo), mas não é garantido que o token do grupo posterior chegue a algum lugar seguro (se for seguro executar um erro fatal)

\documentclass{article}
\usepackage{expl3}
\usepackage{everypage}

\ExplSyntaxOn

\AddEverypageHook { \sean_do_test: }
\cs_new:Nn \sean_do_test:
 {
  \bool_if:nTF { \mode_if_inner_p: || \mode_if_horizontal_p: }
   {
    \group_insert_after:N \sean_do_test:
   }
   {
    \sean_test:
   }
 }


\msg_new:nnnn { test } { message }
  { this ~ is ~ a ~ rubbish ~ message }
  { it's ~ a ~ minimal ~ example }

\cs_new_protected:Npn \sean_test:
  {
    \typeout{++before++}
    \msg_fatal:nn { test } { message }
    \typeout{++after++}
  }

\ExplSyntaxOff

\usepackage{mwe}
\begin{document}
\lipsum[1-1000]
\end{document}

Responder2

A fatalclasse de erros é realmente destinada a problemas graves, quase certamente em tempo de carregamento. No seu exemplo, você acabou dentro de uma caixa: o TeX não nos permite 'resgatar' lá, daí o erro. Talvez pudéssemos adicionar um guarda para verificar o modo atual e apenas tentar \endse for permitido, mas essencialmente este não é o lugar “certo” para ocorrer um erro fatal.

informação relacionada