Skip to main content

victauri_plugin/
error.rs

1//! Typed error enums for the `victauri-plugin` crate.
2
3/// Errors that can occur when building the Victauri plugin via [`crate::VictauriBuilder`].
4#[derive(Debug, thiserror::Error)]
5#[non_exhaustive]
6pub enum BuilderError {
7    /// The configured port is invalid (e.g., port 0).
8    #[error("invalid port {port}: {reason}")]
9    InvalidPort {
10        /// The invalid port number.
11        port: u16,
12        /// Why the port is invalid.
13        reason: String,
14    },
15
16    /// The event log capacity is out of the valid range.
17    #[error("invalid event capacity {capacity}: {reason}")]
18    InvalidEventCapacity {
19        /// The invalid capacity value.
20        capacity: usize,
21        /// Why the capacity is invalid.
22        reason: String,
23    },
24
25    /// The recorder capacity is out of the valid range.
26    #[error("invalid recorder capacity {capacity}: {reason}")]
27    InvalidRecorderCapacity {
28        /// The invalid capacity value.
29        capacity: usize,
30        /// Why the capacity is invalid.
31        reason: String,
32    },
33
34    /// The eval timeout is out of the valid range.
35    #[error("invalid eval timeout {timeout_secs}s: {reason}")]
36    InvalidEvalTimeout {
37        /// The invalid timeout in seconds.
38        timeout_secs: u64,
39        /// Why the timeout is invalid.
40        reason: String,
41    },
42}
43
44/// Errors that can occur during MCP server operation, tool execution, or webview interaction.
45#[derive(Debug, thiserror::Error)]
46#[non_exhaustive]
47pub enum PluginError {
48    /// A JavaScript eval timed out waiting for a response from the webview.
49    #[error("eval timed out after {timeout_secs}s")]
50    EvalTimeout {
51        /// How many seconds elapsed before the timeout.
52        timeout_secs: u64,
53    },
54
55    /// A JavaScript eval returned an error from the webview.
56    #[error("eval failed: {message}")]
57    EvalFailed {
58        /// The error message from the webview.
59        message: String,
60    },
61
62    /// Too many concurrent eval requests are pending.
63    #[error("too many concurrent eval requests (limit: {limit})")]
64    EvalConcurrencyExceeded {
65        /// The maximum number of concurrent eval requests.
66        limit: usize,
67    },
68
69    /// The webview bridge returned an error.
70    #[error("bridge error: {message}")]
71    BridgeError {
72        /// The error message from the bridge.
73        message: String,
74    },
75
76    /// Screenshot capture failed.
77    #[error("screenshot failed: {message}")]
78    ScreenshotFailed {
79        /// The error message from the screenshot subsystem.
80        message: String,
81    },
82
83    /// Bearer-token authentication failed.
84    #[error("authentication failed: {message}")]
85    AuthenticationFailed {
86        /// The error message describing the auth failure.
87        message: String,
88    },
89
90    /// The rate limiter rejected the request.
91    #[error("rate limit exceeded")]
92    RateLimitExceeded,
93
94    /// The requested tool is disabled by the privacy configuration.
95    #[error("tool '{tool_name}' is disabled by privacy configuration")]
96    ToolDisabled {
97        /// Name of the disabled tool.
98        tool_name: String,
99    },
100
101    /// The requested command is blocked by the privacy configuration.
102    #[error("command '{command}' is blocked by privacy configuration")]
103    CommandBlocked {
104        /// Name of the blocked command.
105        command: String,
106    },
107
108    /// No window with the given label was found.
109    #[error("window not found: {label}")]
110    WindowNotFound {
111        /// The window label that was not found.
112        label: String,
113    },
114
115    /// The MCP server failed to start (e.g., all ports in use).
116    #[error("MCP server failed to start: {message}")]
117    ServerStartFailed {
118        /// The error message from the server startup.
119        message: String,
120    },
121
122    /// The configured port is already bound by another process.
123    #[error("port {port} is already in use")]
124    PortInUse {
125        /// The port that is already in use.
126        port: u16,
127    },
128
129    /// JSON serialization or deserialization failed.
130    #[error("serialization error: {0}")]
131    Serialization(#[from] serde_json::Error),
132
133    /// An I/O operation failed.
134    #[error("I/O error: {0}")]
135    Io(#[from] std::io::Error),
136
137    /// A URL failed validation.
138    #[error("invalid URL: {message}")]
139    InvalidUrl {
140        /// The error message describing why the URL is invalid.
141        message: String,
142    },
143
144    /// An error propagated from the `victauri-core` crate.
145    #[error(transparent)]
146    Core(#[from] victauri_core::VictauriError),
147}
148
149/// Convenience alias for `std::result::Result<T, PluginError>`.
150pub type Result<T> = std::result::Result<T, PluginError>;