-
Notifications
You must be signed in to change notification settings - Fork 139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cnd_message()
is called twice in rlang::abort()
within reprex::reprex()
#1205
Comments
cnd_message()
is called twice in rlang::abort()
cnd_message()
is called twice in rlang::abort()
within reprex::reprex()
This is only the case within I'm not sure we'll get around to fixing that soon but I'll have a look in case something obvious is missing. |
@lionel-, |
Does this have any bearing on tidyverse/reprex#230? In general, once you merge this @lionel-, I would love for you to look at reprex's options and tell me what you think is most appropriate: |
Unfortunately this doesn't help with tidyverse/reprex#230, we still need some calling-handler hook in evaluate and knitr to entrace the base errors. Is this something that I should bump on my priority list? Regarding the relevant rlang options for reprex following these changes, I'll open an issue after I have fixed #932. |
Thanks!
No special priority for me or reprex, no. |
Disclaimer: I do understand this is an experimental feature, but to me this looks like an exceptionally important feature for package maintainers and users of {rlang}.
rlang::abort()
allows throwing errors of a derived type with additional data attached to them. This is great for extensibility, as consumers of {rlang} can define their own error class and provide some generics to improve error printing. At the same time, consumers can rely on {ralng}'s formatting methods forrlang_error
, which print out additional info like backtraces, parents, etc.Right now, the suggested approach is to implement
S3
genericsrlang::cnd_header()
,rlang::cnd_body()
,rlang::cnd_footer()
for a derived type to improve printing.The default implementation used for formatting
ralgn_error
seems to just return the$message
field incnd_header.default()
.So, if one would like to print additional info (e.g., using metadata attached as fields to the thrown error), all the logic can be put in, say,
cnd_header()
.At this point, I assume that
S3
can be used to implement a proper 'virtual' method using something likeThe expected behavior is that when printed,
my_error
will display both its$message
field through default implementation and some additional info.Here is a reprex with inheritance. I copy-paste the output:
Code
Regular output
However, this is what happens if instead this same snippet is executed using {reprex}:
Reprex
Created on 2021-05-14 by the reprex package (v2.0.0)
The messages written by derived methods actually repeat themselves twice. I spent a lot of time trying to understand what is going on. The problem can be understood if a traceback is printed from the derived formatting method:
With traces
Created on 2021-05-14 by the reprex package (v2.0.0)
For some reason, when executed with {reprex}, the
cnd_message()
gets called twice, and its results are accumulated.This is likely the place the first time
cnd_message()
is called viaconditionMessage.rlang_error()
.rlang/R/cnd-abort.R
Lines 198 to 210 in bda055d
The message gets formatted and written to the
$message
field offallback
.And then the second trace originates from here:
rlang/R/cnd-abort.R
Lines 220 to 222 in bda055d
Where
cnd_message()
gets called on an already modifiedfallback
, so the message is duplicated. And this behavior somehow depends on how it's being executed.This seems to occur in
rlang::abort()
andrlang:::signal_abort()
(perhaps in the basesignalCondition()
).If an error condition is simply created using
rlang::error_cnd()
, things work just fine.Only creation
Created on 2021-05-14 by the reprex package (v2.0.0)
The text was updated successfully, but these errors were encountered: