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 theDisplayof just the first error, without any of the other errors in the chain or the root cause. -
{:#}: Prints theDisplayof 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 theDisplayof 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, theRUST_BACKTRACEenvironment variable is set and non-zero, and the platform is supported by Rust’s standard library’sBacktracetype) 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 theError. 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
impl Error
pub fn new<E>(error: E) -> Error
pub fn new<E>(error: E) -> Error
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
pub fn msg<M>(message: M) -> Error
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
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
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
pub fn context<C>(self, context: C) -> Error
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
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::Backtracesupports the platform - The
RUST_BACKTRACEorRUST_LIB_BACKTRACEenvironment 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<'_> ⓘ
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)
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
pub fn is<E>(&self) -> bool
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>
pub fn downcast<E>(self) -> Result<E, Error>
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>
pub fn downcast_ref<E>(&self) -> Option<&E>
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>
pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
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>
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.0pub fn is<T>(&self) -> boolwhere
T: Error + 'static,
pub fn is<T>(&self) -> boolwhere
T: Error + 'static,
Returns true if the inner type is the same as T.
1.3.0pub fn downcast_ref<T>(&self) -> Option<&T>where
T: Error + 'static,
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.0pub fn is<T>(&self) -> boolwhere
T: Error + 'static,
pub fn is<T>(&self) -> boolwhere
T: Error + 'static,
Forwards to the method defined on the type dyn Error.
1.3.0pub fn downcast_ref<T>(&self) -> Option<&T>where
T: Error + 'static,
pub fn downcast_ref<T>(&self) -> Option<&T>where
T: Error + 'static,
Forwards to the method defined on the type dyn Error.
1.3.0pub fn is<T>(&self) -> boolwhere
T: Error + 'static,
pub fn is<T>(&self) -> boolwhere
T: Error + 'static,
Forwards to the method defined on the type dyn Error.
1.3.0pub fn downcast_ref<T>(&self) -> Option<&T>where
T: Error + 'static,
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)
pub fn sources(&self) -> Source<'_> ⓘ
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<T> Context<T, Error> for Result<T, Error>
impl<T> Context<T, Error> for Result<T, Error>
§impl From<Error> for Error
Available on crate feature anyhow only.Convert a wasmtime::Error into an anyhow::Error.
impl From<Error> for Error
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);