Cloning "anyhow::Error"

Surprisingly, anyhow::Error does not implement clone() or copy(). What's the proper approach when a copy of an error is needed?

(Use case: I/O error reading game asset can result in multiple objects being tagged with a non-fatal error.)

You can downcast the error to concrete type then clone it.

1 Like

Rust's io::Error is not cloneable either. I recommend replacing the error object with your own type.

1 Like

You can store it as Arc<anyhow::Error>. But yeah, the practice is that operational errors are not values. They are neither Clone nor Eq, and really work only for bubbling out and displaying. If you need to store an error, it's better to lower it to some POD representation, like

#[derive(Clone, Eq, Hash, Serialize)]
pub struct CannedError {
    pub code: i32,
    pub message: String

impl From<io::Error> for CannedError { ... }

The other posts are giving good answers to your actual problem, but I think this "Surprisingly" is a good learning opportunity. What would it mean if it did implement those?

  • If it was Copy, then it couldn't store anything dynamically-allocated. That means no Strings, for the simplest example, which would be quite limiting.

  • To provide Clone, it would only be able to store cloneable errors -- since Clone isn't fallible -- which as kornel mentions would keep it from being useful with common std errors. Maybe one day it will be able to use specialization to offer a try_clone kind of API, but that doesn't exist yet on stable.


That's the most useful solution.

Why are the standard errors not cloneable? Tradition? Fear of causing allocation during destruction?

Flexibility, backwards compatibility:

let _ = io::Error::new(io::ErrorKind::Other, MyNonCloneError);

I think there’s a much more specific reason. Many errors (including io::Error) store a type-erased variant:

Box<dyn error::Error + Send + Sync>

Rust just doesn’t allow such dyn objects to be Clone or Eq in a nice way. Even if you add Clone and Eq to the Error’s super-traits, this won’t just extend to a trait object, you’ll have to do some extra dancing, like here:


That dancing doesn't have to be particularly onerous. A while back I answered a question about a blog post which found a similar way to impl Clone for Box<dyn MyTrait>. The trick is to add a supertrait with fn clone_box(&self) -> Box<dyn MyTrait>, add a blanket impl for all MyTrait + Clone + 'static types, and call self.clone_box() in the final Clone impl (playground):

pub trait DNSRecord: DNSRecordClone {
    fn get_name(&self) -> String;
    fn get_type(&self) -> u16;
    fn get_class(&self) -> u16;
    fn get_ttl(&self) -> u32;
    fn get_rdlength(&self) -> u16;
    fn get_rdata(&self) -> String;

pub trait DNSRecordClone {
    fn clone_box(&self) -> Box<dyn DNSRecord>;

impl<T: DNSRecord + Clone + 'static> DNSRecordClone for T {
    fn clone_box(&self) -> Box<dyn DNSRecord> {

impl Clone for Box<dyn DNSRecord> {
    fn clone(&self) -> Box<dyn DNSRecord> {

(Someone could probably write a proc macro for this.)

Someone already wrote a macro for this.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.