error.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // Copyright 2019-2022 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use std::{fmt, path::PathBuf};
  5. /// A generic boxed error.
  6. #[derive(Debug)]
  7. pub struct SetupError(Box<dyn std::error::Error>);
  8. impl From<Box<dyn std::error::Error>> for SetupError {
  9. fn from(error: Box<dyn std::error::Error>) -> Self {
  10. Self(error)
  11. }
  12. }
  13. // safety: the setup error is only used on the main thread
  14. // and we exit the process immediately.
  15. unsafe impl Send for SetupError {}
  16. unsafe impl Sync for SetupError {}
  17. impl fmt::Display for SetupError {
  18. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  19. self.0.fmt(f)
  20. }
  21. }
  22. impl std::error::Error for SetupError {}
  23. /// Runtime errors that can happen inside a Tauri application.
  24. #[derive(Debug, thiserror::Error)]
  25. #[non_exhaustive]
  26. pub enum Error {
  27. /// Runtime error.
  28. #[error("runtime error: {0}")]
  29. Runtime(#[from] tauri_runtime::Error),
  30. /// Failed to create window.
  31. #[error("failed to create window")]
  32. CreateWindow,
  33. /// Window label must be unique.
  34. #[error("a window with label `{0}` already exists")]
  35. WindowLabelAlreadyExists(String),
  36. /// Can't access webview dispatcher because the webview was closed or not found.
  37. #[error("webview not found: invalid label or it was closed")]
  38. WebviewNotFound,
  39. /// Failed to send message to webview.
  40. #[error("failed to send message to the webview")]
  41. FailedToSendMessage,
  42. /// Embedded asset not found.
  43. #[error("asset not found: {0}")]
  44. AssetNotFound(String),
  45. /// Failed to serialize/deserialize.
  46. #[error("JSON error: {0}")]
  47. Json(serde_json::Error),
  48. /// Unknown API type.
  49. #[error("unknown API: {0:?}")]
  50. UnknownApi(Option<serde_json::Error>),
  51. /// Failed to execute tauri API.
  52. #[error("failed to execute API: {0}")]
  53. FailedToExecuteApi(#[from] crate::api::Error),
  54. /// IO error.
  55. #[error("{0}")]
  56. Io(#[from] std::io::Error),
  57. /// Failed to decode base64.
  58. #[cfg(feature = "updater")]
  59. #[error("Failed to decode base64 string: {0}")]
  60. Base64Decode(#[from] base64::DecodeError),
  61. /// Failed to load window icon.
  62. #[error("invalid icon: {0}")]
  63. InvalidIcon(std::io::Error),
  64. /// Client with specified ID not found.
  65. #[error("http client dropped or not initialized")]
  66. HttpClientNotInitialized,
  67. /// API not whitelisted on tauri.conf.json
  68. #[error("'{0}' not in the allowlist (https://tauri.app/docs/api/config#tauri.allowlist)")]
  69. ApiNotAllowlisted(String),
  70. /// Invalid args when running a command.
  71. #[error("invalid args `{1}` for command `{0}`: {2}")]
  72. InvalidArgs(&'static str, &'static str, serde_json::Error),
  73. /// Encountered an error in the setup hook,
  74. #[error("error encountered during setup hook: {0}")]
  75. Setup(SetupError),
  76. /// Tauri updater error.
  77. #[cfg(updater)]
  78. #[cfg_attr(doc_cfg, doc(cfg(feature = "updater")))]
  79. #[error("Updater: {0}")]
  80. TauriUpdater(#[from] crate::updater::Error),
  81. /// Error initializing plugin.
  82. #[error("failed to initialize plugin `{0}`: {1}")]
  83. PluginInitialization(String, String),
  84. /// A part of the URL is malformed or invalid. This may occur when parsing and combining
  85. /// user-provided URLs and paths.
  86. #[error("invalid url: {0}")]
  87. InvalidUrl(url::ParseError),
  88. /// Task join error.
  89. #[error(transparent)]
  90. JoinError(#[from] tokio::task::JoinError),
  91. /// Path not allowed by the scope.
  92. #[error("path not allowed on the configured scope: {0}")]
  93. PathNotAllowed(PathBuf),
  94. /// The user did not allow sending notifications.
  95. #[error("sending notification was not allowed by the user")]
  96. NotificationNotAllowed,
  97. /// URL not allowed by the scope.
  98. #[error("url not allowed on the configured scope: {0}")]
  99. UrlNotAllowed(url::Url),
  100. /// Sidecar not allowed by the configuration.
  101. #[error("sidecar not configured under `tauri.conf.json > tauri > bundle > externalBin`: {0}")]
  102. SidecarNotAllowed(PathBuf),
  103. /// Sidecar was not found by the configuration.
  104. #[cfg(shell_scope)]
  105. #[error("sidecar configuration found, but unable to create a path to it: {0}")]
  106. SidecarNotFound(#[from] Box<crate::ShellScopeError>),
  107. /// Program not allowed by the scope.
  108. #[error("program not allowed on the configured shell scope: {0}")]
  109. ProgramNotAllowed(PathBuf),
  110. /// An error happened inside the isolation pattern.
  111. #[cfg(feature = "isolation")]
  112. #[error("isolation pattern error: {0}")]
  113. IsolationPattern(#[from] tauri_utils::pattern::isolation::Error),
  114. /// An invalid window URL was provided. Includes details about the error.
  115. #[error("invalid window url: {0}")]
  116. InvalidWindowUrl(&'static str),
  117. /// Invalid glob pattern.
  118. #[error("invalid glob pattern: {0}")]
  119. GlobPattern(#[from] glob::PatternError),
  120. /// Error decoding PNG image.
  121. #[cfg(feature = "icon-png")]
  122. #[error("failed to decode PNG: {0}")]
  123. PngDecode(#[from] png::DecodingError),
  124. /// The Window's raw handle is invalid for the platform.
  125. #[error("Unexpected `raw_window_handle` for the current platform")]
  126. InvalidWindowHandle,
  127. /// JNI error.
  128. #[cfg(target_os = "android")]
  129. #[error("jni error: {0}")]
  130. Jni(#[from] jni::errors::Error),
  131. }
  132. pub(crate) fn into_anyhow<T: std::fmt::Display>(err: T) -> anyhow::Error {
  133. anyhow::anyhow!(err.to_string())
  134. }
  135. impl Error {
  136. #[allow(dead_code)]
  137. pub(crate) fn into_anyhow(self) -> anyhow::Error {
  138. anyhow::anyhow!(self.to_string())
  139. }
  140. }
  141. impl From<serde_json::Error> for Error {
  142. fn from(error: serde_json::Error) -> Self {
  143. if error.to_string().contains("unknown variant") {
  144. Self::UnknownApi(Some(error))
  145. } else {
  146. Self::Json(error)
  147. }
  148. }
  149. }