tauri/
error.rs

1// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
2// SPDX-License-Identifier: Apache-2.0
3// SPDX-License-Identifier: MIT
4
5use std::fmt;
6
7/// A generic boxed error.
8#[derive(Debug)]
9pub struct SetupError(Box<dyn std::error::Error>);
10
11impl From<Box<dyn std::error::Error>> for SetupError {
12  fn from(error: Box<dyn std::error::Error>) -> Self {
13    Self(error)
14  }
15}
16
17// safety: the setup error is only used on the main thread
18// and we exit the process immediately.
19unsafe impl Send for SetupError {}
20unsafe impl Sync for SetupError {}
21
22impl fmt::Display for SetupError {
23  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24    self.0.fmt(f)
25  }
26}
27
28impl std::error::Error for SetupError {}
29
30/// Runtime errors that can happen inside a Tauri application.
31#[derive(Debug, thiserror::Error)]
32#[non_exhaustive]
33pub enum Error {
34  /// Runtime error.
35  #[error("runtime error: {0}")]
36  Runtime(#[from] tauri_runtime::Error),
37  /// Window label must be unique.
38  #[error("a window with label `{0}` already exists")]
39  WindowLabelAlreadyExists(String),
40  /// Webview label must be unique.
41  #[error("a webview with label `{0}` already exists")]
42  WebviewLabelAlreadyExists(String),
43  /// Cannot use the webview reparent function on webview windows.
44  #[error("cannot reparent when using a WebviewWindow")]
45  CannotReparentWebviewWindow,
46  /// Embedded asset not found.
47  #[error("asset not found: {0}")]
48  AssetNotFound(String),
49  /// Failed to serialize/deserialize.
50  #[error("JSON error: {0}")]
51  Json(#[from] serde_json::Error),
52  /// IO error.
53  #[error("{0}")]
54  Io(#[from] std::io::Error),
55  /// Failed to load window icon.
56  #[error("invalid icon: {0}")]
57  InvalidIcon(std::io::Error),
58  /// Invalid args when running a command.
59  #[error("invalid args `{1}` for command `{0}`: {2}")]
60  InvalidArgs(&'static str, &'static str, serde_json::Error),
61  /// Encountered an error in the setup hook,
62  #[error("error encountered during setup hook: {0}")]
63  Setup(SetupError),
64  /// Error initializing plugin.
65  #[error("failed to initialize plugin `{0}`: {1}")]
66  PluginInitialization(String, String),
67  /// A part of the URL is malformed or invalid. This may occur when parsing and combining
68  /// user-provided URLs and paths.
69  #[error("invalid url: {0}")]
70  InvalidUrl(url::ParseError),
71  /// Task join error.
72  #[error(transparent)]
73  JoinError(#[from] tokio::task::JoinError),
74  /// An error happened inside the isolation pattern.
75  #[cfg(feature = "isolation")]
76  #[error("isolation pattern error: {0}")]
77  IsolationPattern(#[from] tauri_utils::pattern::isolation::Error),
78  /// An invalid window URL was provided. Includes details about the error.
79  #[error("invalid window url: {0}")]
80  InvalidWebviewUrl(&'static str),
81  /// Invalid glob pattern.
82  #[error("invalid glob pattern: {0}")]
83  GlobPattern(#[from] glob::PatternError),
84  /// Image error.
85  #[cfg(any(feature = "image-png", feature = "image-ico"))]
86  #[error("failed to process image: {0}")]
87  Image(#[from] image::error::ImageError),
88  /// The Window's raw handle is invalid for the platform.
89  #[error("Unexpected `raw_window_handle` for the current platform")]
90  InvalidWindowHandle,
91  /// JNI error.
92  #[cfg(target_os = "android")]
93  #[error("jni error: {0}")]
94  Jni(#[from] jni::errors::Error),
95  /// Failed to receive message .
96  #[error("failed to receive message")]
97  FailedToReceiveMessage,
98  /// Menu error.
99  #[error("menu error: {0}")]
100  #[cfg(desktop)]
101  Menu(#[from] muda::Error),
102  /// Bad menu icon error.
103  #[error(transparent)]
104  #[cfg(desktop)]
105  BadMenuIcon(#[from] muda::BadIcon),
106  /// Tray icon error.
107  #[error("tray icon error: {0}")]
108  #[cfg(all(desktop, feature = "tray-icon"))]
109  #[cfg_attr(docsrs, doc(cfg(all(desktop, feature = "tray-icon"))))]
110  Tray(#[from] tray_icon::Error),
111  /// Bad tray icon error.
112  #[error(transparent)]
113  #[cfg(all(desktop, feature = "tray-icon"))]
114  #[cfg_attr(docsrs, doc(cfg(all(desktop, feature = "tray-icon"))))]
115  BadTrayIcon(#[from] tray_icon::BadIcon),
116  /// Path does not have a parent.
117  #[error("path does not have a parent")]
118  NoParent,
119  /// Path does not have an extension.
120  #[error("path does not have an extension")]
121  NoExtension,
122  /// Path does not have a basename.
123  #[error("path does not have a basename")]
124  NoBasename,
125  /// Cannot resolve current directory.
126  #[error("failed to read current dir: {0}")]
127  CurrentDir(std::io::Error),
128  /// Unknown path.
129  #[cfg(not(target_os = "android"))]
130  #[error("unknown path")]
131  UnknownPath,
132  /// Failed to invoke mobile plugin.
133  #[cfg(target_os = "android")]
134  #[error(transparent)]
135  PluginInvoke(#[from] crate::plugin::mobile::PluginInvokeError),
136  /// window not found.
137  #[error("window not found")]
138  WindowNotFound,
139  /// The resource id is invalid.
140  #[error("The resource id {0} is invalid.")]
141  BadResourceId(crate::resources::ResourceId),
142  /// The anyhow crate error.
143  #[error(transparent)]
144  Anyhow(#[from] anyhow::Error),
145  /// webview not found.
146  #[error("webview not found")]
147  WebviewNotFound,
148  /// API requires the unstable feature flag.
149  #[error("this feature requires the `unstable` flag on Cargo.toml")]
150  UnstableFeatureNotSupported,
151  /// Failed to deserialize scope object.
152  #[error("error deserializing scope: {0}")]
153  CannotDeserializeScope(Box<dyn std::error::Error + Send + Sync>),
154  /// Failed to get a raw handle.
155  #[error(transparent)]
156  RawHandleError(#[from] raw_window_handle::HandleError),
157  /// Something went wrong with the CSPRNG.
158  #[error("unable to generate random bytes from the operating system: {0}")]
159  Csprng(getrandom::Error),
160  /// Bad `__TAURI_INVOKE_KEY__` value received in ipc message.
161  #[error("bad __TAURI_INVOKE_KEY__ value received in ipc message")]
162  InvokeKey,
163  /// Illegal event name.
164  #[error("only alphanumeric, '-', '/', ':', '_' permitted for event names: {0:?}")]
165  IllegalEventName(String),
166  /// tokio oneshot channel failed to receive message
167  #[error(transparent)]
168  TokioOneshotRecv(#[from] tokio::sync::oneshot::error::RecvError),
169}
170
171impl From<getrandom::Error> for Error {
172  fn from(value: getrandom::Error) -> Self {
173    Self::Csprng(value)
174  }
175}
176
177/// `Result<T, ::tauri::Error>`
178pub type Result<T> = std::result::Result<T, Error>;
179
180#[cfg(test)]
181mod tests {
182  #[test]
183  fn error_is_send_sync() {
184    crate::test_utils::assert_send::<super::Error>();
185    crate::test_utils::assert_sync::<super::Error>();
186  }
187}