Skip to main content

scarab_plugin_api/
error.rs

1//! Error types for plugin operations
2
3use thiserror::Error;
4
5#[derive(Error, Debug)]
6pub enum PluginError {
7    #[error("Plugin failed to load: {0}")]
8    LoadError(String),
9
10    #[error("Plugin version incompatible: required {required}, got {actual}")]
11    VersionIncompatible { required: String, actual: String },
12
13    #[error("Plugin hook execution timed out after {0}ms")]
14    Timeout(u64),
15
16    #[error("Plugin panic: {0}")]
17    Panic(String),
18
19    #[error("Plugin disabled due to repeated failures")]
20    Disabled,
21
22    #[error("Configuration error: {0}")]
23    ConfigError(String),
24
25    #[error("IO error: {0}")]
26    IoError(#[from] std::io::Error),
27
28    #[error("TOML parse error: {0}")]
29    TomlError(#[from] toml::de::Error),
30
31    #[error("Invalid plugin metadata: {0}")]
32    InvalidMetadata(String),
33
34    #[error("Plugin not found: {0}")]
35    NotFound(String),
36
37    #[error("Capability denied: {0}")]
38    CapabilityDenied(String),
39
40    #[error("Quota exceeded for {resource}: {current}/{limit}")]
41    QuotaExceeded {
42        resource: String,
43        current: usize,
44        limit: usize,
45    },
46
47    #[error("Rate limit exceeded: {current} actions (limit: {limit}/sec)")]
48    RateLimitExceeded { current: u32, limit: u32 },
49
50    #[error("Validation error: {0}")]
51    ValidationError(String),
52
53    #[error("Other error: {0}")]
54    Other(#[from] anyhow::Error),
55}
56
57impl PluginError {
58    /// Get friendly suggestions for fixing this error
59    pub fn suggestions(&self) -> Vec<&'static str> {
60        match self {
61            PluginError::LoadError(_) => vec![
62                "Check that the plugin file exists and has the correct extension (.fzb or .fsx)",
63                "Verify the plugin file isn't corrupted",
64                "Make sure you have read permissions for the plugin file",
65                "Try loading the plugin with the full absolute path",
66            ],
67            PluginError::VersionIncompatible { .. } => vec![
68                "Update the plugin to match the current API version",
69                "Check if a newer version of the plugin is available",
70                "Update Scarab to support the plugin's API version",
71                "Contact the plugin author about compatibility",
72            ],
73            PluginError::Timeout(_) => vec![
74                "The plugin might be doing too much work in its hooks",
75                "Try optimizing the plugin's hook implementations",
76                "Check if the plugin is waiting on external resources",
77                "Increase the timeout with --timeout flag if needed",
78            ],
79            PluginError::ConfigError(_) => vec![
80                "Check your plugins.toml file for syntax errors",
81                "Verify all required configuration fields are present",
82                "Make sure the configuration values have the correct types",
83                "Look at example configurations in the docs",
84            ],
85            PluginError::NotFound(_) => vec![
86                "Double-check the file path in your configuration",
87                "Make sure the plugin file is in one of the search paths",
88                "Use an absolute path instead of a relative one",
89                "Check if ~ expansion is working correctly",
90            ],
91            PluginError::Disabled => vec![
92                "Check the plugin logs for recurring errors",
93                "The plugin exceeded the maximum failure count",
94                "Try fixing the plugin and restarting Scarab",
95                "You can re-enable it in plugins.toml once fixed",
96            ],
97            PluginError::CapabilityDenied(_) => vec![
98                "The plugin lacks the required capability for this action",
99                "Check the plugin's manifest for declared capabilities",
100                "Request additional capabilities in plugin.toml",
101            ],
102            PluginError::QuotaExceeded { .. } => vec![
103                "The plugin has exceeded its resource quota",
104                "Reduce the number of registered resources",
105                "Unregister unused focusables or overlays",
106                "Request higher quotas in plugin configuration",
107            ],
108            PluginError::RateLimitExceeded { .. } => vec![
109                "The plugin is making too many API calls per second",
110                "Add delays between API calls",
111                "Batch operations where possible",
112            ],
113            PluginError::ValidationError(_) => vec![
114                "Check the input data against validation constraints",
115                "Ensure coordinates are within terminal bounds",
116                "Verify URLs use allowed protocols (http/https)",
117            ],
118            _ => vec!["Check the plugin documentation for more help"],
119        }
120    }
121
122    /// Format error with friendly prefix and suggestions
123    pub fn friendly_message(&self) -> String {
124        use crate::delight;
125        delight::friendly_error(&self.to_string(), self.suggestions())
126    }
127}
128
129pub type Result<T> = std::result::Result<T, PluginError>;