wasmer_types/
error.rs

1//! The WebAssembly possible errors
2use crate::{ExternType, Pages, progress::UserAbort};
3use std::io;
4use thiserror::Error;
5
6/// The Serialize error can occur when serializing a
7/// compiled Module into a binary.
8#[derive(Error, Debug)]
9pub enum SerializeError {
10    /// An IO error
11    #[error(transparent)]
12    Io(#[from] io::Error),
13    /// A generic serialization error
14    #[error("{0}")]
15    Generic(String),
16}
17
18/// The Deserialize error can occur when loading a
19/// compiled Module from a binary.
20#[derive(Error, Debug)]
21pub enum DeserializeError {
22    /// An IO error
23    #[error(transparent)]
24    Io(#[from] io::Error),
25    /// A generic deserialization error
26    #[error("{0}")]
27    Generic(String),
28    /// Incompatible serialized binary
29    #[error("incompatible binary: {0}")]
30    Incompatible(String),
31    /// The provided binary is corrupted
32    #[error("corrupted binary: {0}")]
33    CorruptedBinary(String),
34    /// The binary was valid, but we got an error when
35    /// trying to allocate the required resources.
36    #[error(transparent)]
37    Compiler(#[from] CompileError),
38    /// Input artifact bytes have an invalid length
39    #[error("invalid input bytes: expected {expected} bytes, got {got}")]
40    InvalidByteLength {
41        /// How many bytes were expected
42        expected: usize,
43        /// How many bytes the artifact contained
44        got: usize,
45    },
46}
47
48/// Error type describing things that can go wrong when operating on Wasm Memories.
49#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
50#[non_exhaustive]
51pub enum MemoryError {
52    /// Low level error with mmap.
53    #[error("Error when allocating memory: {0}")]
54    Region(String),
55    /// The operation would cause the size of the memory to exceed the maximum or would cause
56    /// an overflow leading to unindexable memory.
57    #[error("The memory could not grow: current size {} pages, requested increase: {} pages", current.0, attempted_delta.0)]
58    CouldNotGrow {
59        /// The current size in pages.
60        current: Pages,
61        /// The attempted amount to grow by in pages.
62        attempted_delta: Pages,
63    },
64    /// Invalid memory was provided.
65    #[error("The memory is invalid because {}", reason)]
66    InvalidMemory {
67        /// The reason why the provided memory is invalid.
68        reason: String,
69    },
70    /// Caller asked for more minimum memory than we can give them.
71    #[error("The minimum requested ({} pages) memory is greater than the maximum allowed memory ({} pages)", min_requested.0, max_allowed.0)]
72    MinimumMemoryTooLarge {
73        /// The number of pages requested as the minimum amount of memory.
74        min_requested: Pages,
75        /// The maximum amount of memory we can allocate.
76        max_allowed: Pages,
77    },
78    /// Caller asked for a maximum memory greater than we can give them.
79    #[error("The maximum requested memory ({} pages) is greater than the maximum allowed memory ({} pages)", max_requested.0, max_allowed.0)]
80    MaximumMemoryTooLarge {
81        /// The number of pages requested as the maximum amount of memory.
82        max_requested: Pages,
83        /// The number of pages requested as the maximum amount of memory.
84        max_allowed: Pages,
85    },
86    /// Returned when a shared memory is required, but the given memory is not shared.
87    #[error("The memory is not shared")]
88    MemoryNotShared,
89    /// Returned when trying to call a memory operation that is not supported by
90    /// the particular memory implementation.
91    #[error("tried to call an unsupported memory operation: {message}")]
92    UnsupportedOperation {
93        /// Message describing the unsupported operation.
94        message: String,
95    },
96    /// An atomic operation failed.
97    #[error("Atomic operation failed: {0}")]
98    AtomicOperationFailed(AtomicsError),
99    /// A user defined error value, used for error cases not listed above.
100    #[error("A user-defined error occurred: {0}")]
101    Generic(String),
102}
103
104/// Error that can occur during atomic operations. (notify/wait)
105// Non-exhaustive to allow for future variants without breaking changes!
106#[derive(PartialEq, Eq, Debug, Error, Clone, Copy, Hash)]
107#[non_exhaustive]
108pub enum AtomicsError {
109    /// Atomic operations are not supported by this memory.
110    #[error("The memory does not support atomic operations")]
111    Unimplemented,
112    /// Too many waiters for address.
113    #[error("Too many waiters for address")]
114    TooManyWaiters,
115    /// Atomic operations are disabled.
116    #[error("Atomic operations are disabled for this memory")]
117    AtomicsDisabled,
118    /// The memory was already dropped.
119    #[error("The memory was already dropped")]
120    MemoryDropped,
121}
122
123/// An ImportError.
124///
125/// Note: this error is not standard to WebAssembly, but it's
126/// useful to determine the import issue on the API side.
127#[derive(Error, Debug, Clone)]
128pub enum ImportError {
129    /// Incompatible Import Type.
130    /// This error occurs when the import types mismatch.
131    #[error("incompatible import type. Expected {0:?} but received {1:?}")]
132    IncompatibleType(ExternType, ExternType),
133
134    /// Unknown Import.
135    /// This error occurs when an import was expected but not provided.
136    #[error("unknown import. Expected {0:?}")]
137    UnknownImport(ExternType),
138
139    /// Memory Error
140    #[error("memory error. {0}")]
141    MemoryError(String),
142}
143
144/// An error while preinstantiating a module.
145///
146#[derive(Error, Debug)]
147pub enum PreInstantiationError {
148    /// The module was compiled with a CPU feature that is not available on
149    /// the current host.
150    #[error("module compiled with CPU feature that is missing from host")]
151    CpuFeature(String),
152}
153
154use crate::lib::std::string::String;
155
156// Compilation Errors
157//
158// If `std` feature is enable, we can't use `thiserror` until
159// https://github.com/dtolnay/thiserror/pull/64 is merged.
160
161/// The WebAssembly.CompileError object indicates an error during
162/// WebAssembly decoding or validation.
163///
164/// This mirrors the WebAssembly `CompileError` API described at
165/// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/CompileError>.
166#[derive(Debug)]
167#[cfg_attr(feature = "std", derive(Error))]
168pub enum CompileError {
169    /// A Wasm translation error occurred.
170    #[cfg_attr(feature = "std", error("WebAssembly translation error: {0}"))]
171    Wasm(WasmError),
172
173    /// A compilation error occurred.
174    #[cfg_attr(feature = "std", error("Compilation error: {0}"))]
175    Codegen(String),
176
177    /// The module did not pass validation.
178    #[cfg_attr(feature = "std", error("Validation error: {0}"))]
179    Validate(String),
180
181    /// The compiler doesn't support a Wasm feature
182    #[cfg_attr(feature = "std", error("Feature {0} is not yet supported"))]
183    UnsupportedFeature(String),
184
185    /// The compiler cannot compile for the given target.
186    /// This can refer to the OS, the chipset or any other aspect of the target system.
187    #[cfg_attr(
188        feature = "std",
189        error("The target {0} is not yet supported (see https://docs.wasmer.io/runtime/features)")
190    )]
191    UnsupportedTarget(String),
192
193    /// Insufficient resources available for execution.
194    #[cfg_attr(feature = "std", error("Insufficient resources: {0}"))]
195    Resource(String),
196
197    /// Middleware error occurred.
198    #[cfg_attr(feature = "std", error("Middleware error: {0}"))]
199    MiddlewareError(String),
200
201    /// Compilation aborted by a user callback.
202    #[cfg_attr(feature = "std", error("Compilation aborted: {0}"))]
203    Aborted(UserAbort),
204}
205
206impl From<WasmError> for CompileError {
207    fn from(original: WasmError) -> Self {
208        Self::Wasm(original)
209    }
210}
211
212impl From<UserAbort> for CompileError {
213    fn from(abort: UserAbort) -> Self {
214        Self::Aborted(abort)
215    }
216}
217
218/// A error in the middleware.
219#[derive(Debug)]
220#[cfg_attr(feature = "std", derive(Error))]
221#[cfg_attr(feature = "std", error("Error in middleware {name}: {message}"))]
222pub struct MiddlewareError {
223    /// The name of the middleware where the error was created
224    pub name: String,
225    /// The error message
226    pub message: String,
227}
228
229impl MiddlewareError {
230    /// Create a new `MiddlewareError`
231    pub fn new<A: Into<String>, B: Into<String>>(name: A, message: B) -> Self {
232        Self {
233            name: name.into(),
234            message: message.into(),
235        }
236    }
237}
238
239impl From<MiddlewareError> for CompileError {
240    fn from(error: MiddlewareError) -> Self {
241        WasmError::Middleware(error).into()
242    }
243}
244
245/// A WebAssembly translation error.
246///
247/// When a WebAssembly function can't be translated, one of these error codes will be returned
248/// to describe the failure.
249#[derive(Debug)]
250#[cfg_attr(feature = "std", derive(Error))]
251pub enum WasmError {
252    /// The input WebAssembly code is invalid.
253    ///
254    /// This error code is used by a WebAssembly translator when it encounters invalid WebAssembly
255    /// code. This should never happen for validated WebAssembly code.
256    #[cfg_attr(
257        feature = "std",
258        error("Invalid input WebAssembly code at offset {offset}: {message}")
259    )]
260    InvalidWebAssembly {
261        /// A string describing the validation error.
262        message: String,
263        /// The bytecode offset where the error occurred.
264        offset: usize,
265    },
266
267    /// A feature used by the WebAssembly code is not supported by the embedding environment.
268    ///
269    /// Embedding environments may have their own limitations and feature restrictions.
270    #[cfg_attr(feature = "std", error("Unsupported feature: {0}"))]
271    Unsupported(String),
272
273    /// An implementation limit was exceeded.
274    #[cfg_attr(feature = "std", error("Implementation limit exceeded"))]
275    ImplLimitExceeded,
276
277    /// An error from the middleware error.
278    #[cfg_attr(feature = "std", error("{0}"))]
279    Middleware(MiddlewareError),
280
281    /// A generic error.
282    #[cfg_attr(feature = "std", error("{0}"))]
283    Generic(String),
284}
285
286impl From<MiddlewareError> for WasmError {
287    fn from(original: MiddlewareError) -> Self {
288        Self::Middleware(original)
289    }
290}
291
292/// The error that can happen while parsing a `str`
293/// to retrieve a [`CpuFeature`](crate::target::CpuFeature).
294#[derive(Debug)]
295#[cfg_attr(feature = "std", derive(Error))]
296pub enum ParseCpuFeatureError {
297    /// The provided string feature doesn't exist
298    #[cfg_attr(feature = "std", error("CpuFeature {0} not recognized"))]
299    Missing(String),
300}
301
302/// A convenient alias for a `Result` that uses `WasmError` as the error type.
303pub type WasmResult<T> = Result<T, WasmError>;
304
305#[cfg(test)]
306mod tests {
307    use super::*;
308
309    #[test]
310    fn middleware_error_can_be_created() {
311        let msg = String::from("Something went wrong");
312        let error = MiddlewareError::new("manipulator3000", msg);
313        assert_eq!(error.name, "manipulator3000");
314        assert_eq!(error.message, "Something went wrong");
315    }
316
317    #[test]
318    fn middleware_error_be_converted_to_wasm_error() {
319        let error = WasmError::from(MiddlewareError::new("manipulator3000", "foo"));
320        match error {
321            WasmError::Middleware(MiddlewareError { name, message }) => {
322                assert_eq!(name, "manipulator3000");
323                assert_eq!(message, "foo");
324            }
325            err => panic!("Unexpected error: {err:?}"),
326        }
327    }
328}