Description
Version
hyper v0.14.17
Description
hyper::Error
's Display
impl will print its immediate cause in a "{description}: {cause}"
format. The problem is this screws with anything else that tries to print an error along with its causes, as the immediate cause is also the returned value from .source()
.
For example, if I were to print an error with tracing
's built-in support, e.g. error!(err as &dyn StdError, "message")
, the resulting log line includes err=error trying to connect: tcp connect error: Connection refused (os error 61) err.sources=[tcp connect error: Connection refused (os error 61), Connection refused (os error 61)]
. Or if I wrap this in an eyre::Report
and print that with {:#}
(which includes the cause chain), I get error trying to connect: tcp connect error: Connection refused (os error 61): tcp connect error: Connection refused (os error 61): Connection refused (os error 61)
which is even more confusing.
This appears to be an intentional decision, especially as it has a .message()
accessor that returns an impl Display
that is just the message. But it's one that is very frustrating. Ideally hyper::Error
would just not include its cause, relying on the user to opt in to showing causes. Alternatively it could just skip the first cause in the .source()
accessor, though that means users who want to actually inspect that cause (e.g. to downcast it) can't (though in the case of the quoted error, its cause is not a public type and so there's nothing I can reasonably do with it besides just printing it).
Changing this behavior will surprise anyone who is currently working around it, though I suspect it will simply produce better behavior for most users who just log the error and move on. My preferred solution of "just don't print the cause" does make the message()
accessor pointless, though that could simply be deprecated without having to do a breaking change.
If you really don't want to make this change, then at least please change the message()
accessor to actually be an impl StdError + Send + Sync
such that I can then pass that to whatever I'm using that logs causes. The resulting error from this would of course retain the initial cause as the source()
. Please also do this even if you decide the right solution is to just skip the initial cause in source()
, so I can still get the formatting I want without having to reinvent error chains (especially when dealing with stuff like eyre::Report
's {:?}
printing).