Error

Struct Error 

pub struct Error { /* private fields */ }
Expand description

Wasmtime’s universal error type.

99% API-compatible with anyhow::Error but additionally allows recovery from memory exhaustion (see the OutOfMemory error).

Error is similar to Box<dyn core::error::Error + Send + Sync + 'static> but fits in one word instead of two. Additionally, Result<(), Error> also fits in a single word.

When the "backtrace" cargo feature is enabled, Error contains a backtrace.

§Creating an Error

Because Error implements From<E> for all types E that implement core::error::Error + Send + Sync + 'static, you don’t usually need to explicitly construct an Error. When you use ?-style error propagation, it will automatically get constructed from the root cause error for you.

Most often when creating an Error, you just want to early-exit from the function, returning Err(...). The ensure! macro early-returns an error when a condition is not met (similar to how assert! panics when a condition is not met) and the bail! macro early-returns an error unconditionally.

use wasmtime::{bail, ensure, Result};

fn my_fallible_function(x: u32) -> Result<()> {
    // This `ensure!` macro invocation is equivalent to
    //
    //     if x % 2 != 0 {
    //         return Err(...);
    //     }
    ensure!(x % 2 == 0, "{x} is not even!");

    // This `bail!` macro invocation is equivalent to
    //
    //     return Err(...);
    bail!("oops, another error! {x}")
}

If you do not want to early-return, just to create the Error, then the format_err! macro is preferred:

use wasmtime::{format_err, Error};

let x = 42;
let my_error: Error = format_err!("whoops! {x}");

If, however, you happen to require a constructor function instead of a macro, you can use either Error::new or Error::msg:

use wasmtime::Error;

let messages = ["yikes", "uh oh", "ouch"];
let errors = messages
    .into_iter()
    .map(Error::msg)
    .collect::<Vec<_>>();

§Printing an Error

Different format strings will print an Error differently:

  • {}: Prints the Display of just the first error, without any of the other errors in the chain or the root cause.

  • {:#}: Prints the Display of the first error, then (if there are more errors in the chain) a colon, then the display of the second error in the chain, etc…

  • {:?}: Prints the Display of the first error, then (if there are more errors in the chain) a newline-separated list of the rest of the errors in the chain, and finally (if the "backtrace" cargo feature is enabled, the RUST_BACKTRACE environment variable is set and non-zero, and the platform is supported by Rust’s standard library’s Backtrace type) the captured backtrace is printed.

    This is the default formatting used when fn main() -> wasmtime::Result<()> returns an error.

  • {:#?}: Prints an internal, debugging representation of the Error. We make no guarantees about its stability.

Here is an example showing the different formats for the same error:

#![cfg(all(feature = "backtrace", not(miri)))]
use wasmtime::{bail, Context as _, Result};

fn uno() -> Result<()> {
    bail!("ouch")
}

fn dos() -> Result<()> {
    uno().context("whoops")
}

fn tres() -> Result<()> {
    dos().context("uh oh")
}

let error = tres().unwrap_err();

println!("{error}");
// Prints:
//
//     uh oh

println!("{error:#}");
// Prints:
//
//     uh oh: whoops: ouch

println!("{error:?}");
// Prints
//
//     uh oh
//
//     Caused by:
//         0: whoops
//         1: ouch
//
//     Stack backtrace:
//       <...>
//        7: example::uno
//        8: example::dos
//        9: example::tres
//       10: example::main
//       <...>

println!("{error:#?}");
// Prints
//
//     Error {
//         <...>
//     }

§Converting a wasmtime::Error into an anyhow::Error

When the "anyhow" feature is enabled, there is a From<wasmtime::Error> for anyhow::Error implementation. You can always call that implementation explicitly if needed, but ?-propagation allows the conversion to happen seamlessly from functions that return a Result<T, wasmtime::Error> to those that return a Result<U, anyhow::Error>.

#![cfg(feature = "anyhow")]

fn foo() -> Result<(), wasmtime::Error> {
    wasmtime::bail!("decontamination failure")
}

fn bar() -> Result<(), anyhow::Error> {
    foo()?; // `?` is auto-converting here!
    Ok(())
}

let error = bar().unwrap_err();
assert_eq!(error.to_string(), "decontamination failure");

§Converting an anyhow::Error into a wasmtime::Error

When the "anyhow" feature is enabled, there is an Error::from_anyhow constructor that you may use to convert an anyhow::Error into a wasmtime::Error. (Unfortunately trait coherence does not allow us a From<anyhow::Error> for wasmtime::Error implementation.) This will most-often be used in combination with Result::map_err:

#![cfg(feature = "anyhow")]

fn baz() -> Result<(), anyhow::Error> {
    anyhow::bail!("oops I ate worms")
}

fn qux() -> Result<(), wasmtime::Error> {
    baz().map_err(wasmtime::Error::from_anyhow)?;
    Ok(())
}

let error = qux().unwrap_err();
assert_eq!(error.to_string(), "oops I ate worms");

Implementations§

§

impl Error

pub fn new<E>(error: E) -> Error
where E: Error + Send + Sync + 'static,

Construct a new Error from a type that implements core::error::Error.

Calling error.is::<E>() will return true for the new error (unless there was a memory allocation failure).

This boxes the inner error, but if that box allocation fails, then this function returns an Error where error.is::<OutOfMemory>() is true.

§Example
use wasmtime::Error;

let error = Error::new(std::fmt::Error);

pub fn msg<M>(message: M) -> Error
where M: Debug + Display + Send + Sync + 'static,

Construct a new Error from any type that implements Debug and Display.

Calling error.is::<M>() will return true for the new error (unless there was a memory allocation failure).

This boxes the inner M type, but if that box allocation fails, then this function returns an Error where error.is::<OutOfMemory>() is true.

§Example
use wasmtime::Error;

let error = Error::msg("hello");

pub fn from_boxed(error: Box<dyn Error + Sync + Send>) -> Error

Create an Error from a Box<dyn core::error::Error>.

This is useful when converting errors from other universal-error libraries into this crate’s Error type. Prefer Error::from_anyhow for converting anyhow::Errors into Errors, as that preserves error.is::<anyhow::Error>().

Calling error.is::<Box<dyn core::error::Error + Send + Sync + 'static>>() will return true for the new error (unless there was a memory allocation failure).

This reboxes the inner error, but if that box allocation fails, then this function returns an Error where error.is::<OutOfMemory>() is true.

§Example
#![cfg(all(feature = "std", feature = "anyhow"))]
use std::error::Error;

// You happen to have a boxed error trait object.
let orig_error = std::fs::read("XXX: some file that doesn't exist").unwrap_err();
let boxed_error: Box<dyn Error + Send + Sync + 'static> = Box::new(orig_error) as _;

// You can turn it into a `wasmtime::Error` via `from_boxed`.
let wasmtime_error = wasmtime::Error::from_boxed(boxed_error);

pub fn from_anyhow(error: Error) -> Error

Convert an anyhow::Error into an Error.

Calling error.is::<anyhow::Error>() will return true for the new error (unless there was a memory allocation failure).

This reboxes the anyhow::Error, but if that box allocation fails, then this function returns an Error where error.is::<OutOfMemory>() is true.

§Example
#![cfg(all(feature = "std", feature = "anyhow"))]
let anyhow_error = anyhow::Error::msg("failed to flim the flam");
let wasmtime_error = wasmtime::Error::from_anyhow(anyhow_error);
assert_eq!(
    wasmtime_error.to_string(),
    "failed to flim the flam",
);

pub fn context<C>(self, context: C) -> Error
where C: Display + Send + Sync + 'static,

Add additional context to this error.

The new context will show up first in the error chain, and the original error will come next.

This is similar to the [Context::context] trait method, but because it is a method directly on Error, there is no need for lazily-computing the error context (like with_context does).

Calling error.is::<C>() will return true for the new error (unless there was a memory allocation failure) in addition to any other types T for which it was already the case that error.is::<T>().

This boxes the inner C type, but if that box allocation fails, then this function returns an Error where error.is::<OutOfMemory>() is true.

§Example
use wasmtime::Error;

let error = Error::msg("root cause");
let error = error.context("failed to bonkinate");
let error = error.context("cannot frob the blobbins");

assert!(
    format!("{error:?}").contains(
        r#"
cannot frob the blobbins

Caused by:
    0: failed to bonkinate
    1: root cause
        "#.trim(),
    ),
);

pub fn backtrace(&self) -> &Backtrace

Get this error’s backtrace.

Backtraces will be automatically captured on initial Error creation when all of the following conditions are met:

  • This crate’s "backtrace" cargo feature is enabled
  • Rust’s std::backtrace::Backtrace supports the platform
  • The RUST_BACKTRACE or RUST_LIB_BACKTRACE environment variables are set and non-zero

See the std::backtrace::Backtrace documentation for more details on backtraces.

Note that std::backtrace::Backtrace does not provide a fallible-capture mechanism that returns an error, rather than aborting the process, when it encounters memory exhaustion. If you require out-of-memory error handling, do not enable this crate’s "backtrace" cargo feature.

§Example
#![cfg(feature = "backtrace")]
use std::backtrace::BacktraceStatus;
use wasmtime::Error;

let error = Error::msg("whoops");

let backtrace = error.backtrace();
if let BacktraceStatus::Captured = backtrace.status() {
    println!("error backtrace is:\n{backtrace}");
}

pub fn chain(&self) -> Chain<'_>

Iterate over this error’s context chain.

The iterator yields &(dyn core::error::Error + 'static) items.

Iterates from the most recently added error context towards the root cause.

§Example
use wasmtime::Error;

let error = Error::msg("root cause");
let error = error.context("failed to reticulate splines");
let error = error.context("aborting launch");

let messages: Vec<_> = error.chain().map(|e| e.to_string()).collect();
assert_eq!(
    messages,
    ["aborting launch", "failed to reticulate splines", "root cause"],
);

pub fn root_cause(&self) -> &(dyn Error + 'static)

Get the last error in the context chain.

§Example
use wasmtime::Error;

let error = Error::msg("ghosts");
let error = error.context("failed to reticulate splines");
let error = error.context("aborting launch");

assert_eq!(
    error.root_cause().to_string(),
    "ghosts",
);

pub fn is<E>(&self) -> bool
where E: Display + Debug + Send + Sync + 'static,

Is this an E error?

Returns true if any error in the context chain is an E.

§Example
use wasmtime::{Error, OutOfMemory};

let oom = Error::from(OutOfMemory::new(1234));
assert!(oom.is::<OutOfMemory>());
assert!(!oom.is::<std::num::TryFromIntError>());

// Here is an example with additional error context.
let error = Error::from(u8::try_from(u32::MAX).unwrap_err());
let error = error.context(format!("cannot convert {} into a u8", u32::MAX));
assert!(
    error.is::<std::num::TryFromIntError>(),
    "root cause is an int conversion failure",
);
assert!(
    error.is::<String>(),
    "additional context is a `String`",
);
assert!(
    !error.is::<OutOfMemory>(),
    "no error in the chain is an out-of-memory error",
);

pub fn downcast<E>(self) -> Result<E, Error>
where E: Display + Debug + Send + Sync + 'static,

Downcast this error into an E, taking ownership.

If this error is an E, then Ok(E) is returned. Otherwise, Err(self) is returned.

If there are multiple instances of E in this error’s chain, then the first (as encountered by Error::chain’s iteration order) is returned.

§Example
use wasmtime::{Error, OutOfMemory};

let error = Error::msg("whoops");

// `error` is not an `OutOfMemory`.
let downcasted = error.downcast::<OutOfMemory>();
assert!(downcasted.is_err());

// Get the original `error` back.
let error = downcasted.unwrap_err();

// `error` is an `&str`.
let downcasted = error.downcast::<&str>();
assert!(downcasted.is_ok());
assert_eq!(downcasted.unwrap(), "whoops");

// If there are multiple `E`s in the chain, the first in the chain is
// returned.
let error = Error::msg("root cause");
let error = error.context("failed to recombobulate");
assert_eq!(
    error.downcast::<&str>().unwrap(),
    "failed to recombobulate",
);

pub fn downcast_ref<E>(&self) -> Option<&E>
where E: Display + Debug + Send + Sync + 'static,

Downcast this error into a shared &E borrow.

If this error is an E, then Some(&E) is returned. Otherwise, None is returned.

If there are multiple instances of E in this error’s chain, then the first (as encountered by Error::chain’s iteration order) is returned.

§Example
use wasmtime::{Error, OutOfMemory};

let error = Error::msg("whoops");

// `error` is not an `OutOfMemory`.
assert!(error.downcast_ref::<OutOfMemory>().is_none());

// `error` is an `&str`.
assert!(error.downcast_ref::<&str>().is_some());
assert_eq!(*error.downcast_ref::<&str>().unwrap(), "whoops");

// If there are multiple `E`s in the chain, the first in the chain is
// returned.
let error = Error::msg("root cause");
let error = error.context("failed to recombobulate");
assert_eq!(
    *error.downcast_ref::<&str>().unwrap(),
    "failed to recombobulate",
);

pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
where E: Display + Debug + Send + Sync + 'static,

Downcast this error into an exclusive &mut E borrow.

If this error is an E, then Some(&mut E) is returned. Otherwise, None is returned.

If there are multiple instances of E in this error’s chain, then the first (as encountered by Error::chain’s iteration order) is returned.

§Example
use wasmtime::{Error, OutOfMemory};

let mut error = Error::msg("whoops");

// `error` is not an `OutOfMemory`.
assert!(error.downcast_mut::<OutOfMemory>().is_none());

// `error` is an `&str`.
assert!(error.downcast_mut::<&str>().is_some());
assert_eq!(*error.downcast_mut::<&str>().unwrap(), "whoops");
*error.downcast_mut::<&str>().unwrap() = "yikes";
assert_eq!(*error.downcast_mut::<&str>().unwrap(), "yikes");

// If there are multiple `E`s in the chain, the first in the chain is
// returned.
let error = Error::msg("root cause");
let mut error = error.context("failed to recombobulate");
assert_eq!(
    *error.downcast_mut::<&str>().unwrap(),
    "failed to recombobulate",
);

pub fn into_boxed_dyn_error(self) -> Box<dyn Error + Sync + Send>

Convert this error into a Box<dyn core::error::Error>.

This is useful for integrating this crate’s Errors into other universal-error libraries.

This functionality is also available via a From<Error> for Box<dyn core::error::Error + Send + Sync + 'static>> implementation.

§Example
#![cfg(feature = "std")]
use std::fmt;

/// A stub representing some other error library.
#[derive(Debug)]
pub struct OtherError {
    inner: Box<dyn std::error::Error + Send + Sync + 'static>,
}

impl fmt::Display for OtherError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&self.inner, f)
    }
}

impl std::error::Error for OtherError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        self.inner.source()
    }
}

impl OtherError {
    /// Create an `OtherError` from another error.
    pub fn new<E>(error: E) -> Self
    where
        E: std::error::Error + Send + Sync + 'static,
    {
        OtherError { inner: Box::new(error) }
    }

    /// Create an `OtherError` from another, already-boxed error.
    pub fn from_boxed(error: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self {
        OtherError { inner: error }
    }
}

use wasmtime::Error;

// Create an `Error`.
let error = Error::msg("whoopsies");

// Convert it into an `OtherError`.
let error = OtherError::from_boxed(error.into_boxed_dyn_error());

Methods from Deref<Target = dyn Error + Sync + Send>§

1.3.0

pub fn is<T>(&self) -> bool
where T: Error + 'static,

Returns true if the inner type is the same as T.

1.3.0

pub fn downcast_ref<T>(&self) -> Option<&T>
where T: Error + 'static,

Returns some reference to the inner value if it is of type T, or None if it isn’t.

1.3.0

pub fn is<T>(&self) -> bool
where T: Error + 'static,

Forwards to the method defined on the type dyn Error.

1.3.0

pub fn downcast_ref<T>(&self) -> Option<&T>
where T: Error + 'static,

Forwards to the method defined on the type dyn Error.

1.3.0

pub fn is<T>(&self) -> bool
where T: Error + 'static,

Forwards to the method defined on the type dyn Error.

1.3.0

pub fn downcast_ref<T>(&self) -> Option<&T>
where T: Error + 'static,

Forwards to the method defined on the type dyn Error.

pub fn sources(&self) -> Source<'_>

🔬This is a nightly-only experimental API. (error_iter)

Returns an iterator starting with the current error and continuing with recursively calling Error::source.

If you want to omit the current error and only use its sources, use skip(1).

§Examples
#![feature(error_iter)]
use std::error::Error;
use std::fmt;

#[derive(Debug)]
struct A;

#[derive(Debug)]
struct B(Option<Box<dyn Error + 'static>>);

impl fmt::Display for A {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "A")
    }
}

impl fmt::Display for B {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "B")
    }
}

impl Error for A {}

impl Error for B {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        self.0.as_ref().map(|e| e.as_ref())
    }
}

let b = B(Some(Box::new(A)));

// let err : Box<Error> = b.into(); // or
let err = &b as &dyn Error;

let mut iter = err.sources();

assert_eq!("B".to_string(), iter.next().unwrap().to_string());
assert_eq!("A".to_string(), iter.next().unwrap().to_string());
assert!(iter.next().is_none());
assert!(iter.next().is_none());

Trait Implementations§

§

impl AsRef<dyn Error> for Error

§

fn as_ref(&self) -> &(dyn Error + 'static)

Converts this type into a shared reference of the (usually inferred) input type.
§

impl AsRef<dyn Error + Sync + Send> for Error

§

fn as_ref(&self) -> &(dyn Error + Sync + Send + 'static)

Converts this type into a shared reference of the (usually inferred) input type.
§

impl<T> Context<T, Error> for Result<T, Error>

§

fn context<C>(self, context: C) -> Result<T, Error>
where C: Display + Send + Sync + 'static,

Add additional, already-computed error context to this result. Read more
§

fn with_context<C, F>(self, f: F) -> Result<T, Error>
where C: Display + Send + Sync + 'static, F: FnOnce() -> C,

Add additional, lazily-computed error context to this result. Read more
§

impl Debug for Error

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Deref for Error

§

type Target = dyn Error + Sync + Send

The resulting type after dereferencing.
§

fn deref(&self) -> &<Error as Deref>::Target

Dereferences the value.
§

impl Display for Error

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl<E> From<E> for Error
where E: Error + Send + Sync + 'static,

§

fn from(error: E) -> Error

Converts to this type from the input type.
§

impl From<Error> for Box<dyn Error>

§

fn from(error: Error) -> Box<dyn Error>

Converts to this type from the input type.
§

impl From<Error> for Box<dyn Error + Send>

§

fn from(error: Error) -> Box<dyn Error + Send>

Converts to this type from the input type.
§

impl From<Error> for Box<dyn Error + Sync + Send>

§

fn from(error: Error) -> Box<dyn Error + Sync + Send>

Converts to this type from the input type.
§

impl From<Error> for Error

Available on crate feature anyhow only.

Convert a wasmtime::Error into an anyhow::Error.

§Example

let wasmtime_error = wasmtime::Error::msg("whoops");
let anyhow_error = anyhow::Error::from(wasmtime_error);
§

fn from(e: Error) -> Error

Converts to this type from the input type.

Auto Trait Implementations§

§

impl Freeze for Error

§

impl RefUnwindSafe for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl UnwindSafe for Error

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<!> for T

§

fn from(t: !) -> T

Converts to this type from the input type.
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
§

impl<T> ToString for T
where T: Display + ?Sized,

§

fn to_string(&self) -> String

Converts the given value to a String. Read more
§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.