Skip to main content

wami_core/
error.rs

1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum AmiError {
5    /// A provider rejected an operation.
6    ///
7    /// Replaces the AwsSdk, StsSdk and SsoAdminSdk variants removed in 0.14.
8    /// Those named SDK error types in their signature, so every consumer
9    /// compiled three AWS SDKs to hold three variants this workspace never
10    /// constructed once. Carrying the provider name and its message keeps the
11    /// information without keeping the dependency:
12    ///
13    /// ```ignore
14    /// client.get_user().send().await.map_err(|e| AmiError::Provider {
15    ///     provider: "aws".to_string(),
16    ///     message: e.to_string(),
17    /// })?
18    /// ```
19    #[error("{provider} error: {message}")]
20    Provider {
21        /// Which provider refused.
22        provider: String,
23        /// What it said.
24        message: String,
25    },
26
27    #[error("Serialization error: {0}")]
28    Serialization(#[from] serde_json::Error),
29
30    #[error("Invalid parameter: {message}")]
31    InvalidParameter { message: String },
32
33    #[error("Operation not supported: {operation}")]
34    OperationNotSupported { operation: String },
35
36    #[error("Resource not found: {resource}")]
37    ResourceNotFound { resource: String },
38
39    #[error("Permission denied: {reason}")]
40    PermissionDenied { reason: String },
41
42    #[error("Access denied: {message}")]
43    AccessDenied { message: String },
44
45    #[error("Resource limit exceeded: {resource_type} limit is {limit}")]
46    ResourceLimitExceeded { resource_type: String, limit: usize },
47
48    #[error("Resource already exists: {resource}")]
49    ResourceExists { resource: String },
50
51    #[error("Store error: {0}")]
52    StoreError(String),
53
54    /// A policy document could not be parsed, so no decision can be made from it.
55    ///
56    /// Deliberately an error and not a denial. A denial means "the rules
57    /// forbid this"; an unreadable policy means "the rules cannot be read" —
58    /// and the caller must be able to tell those apart, because the first is a
59    /// 403 the user can act on and the second is a corrupt store that should
60    /// page someone. Folding it into `AccessDenied` would hide a broken policy
61    /// store behind what looks like an ordinary permission failure.
62    #[error("policy cannot be read ({policy}): {message}")]
63    UnreadablePolicy {
64        /// Which policy failed to parse, so an operator knows what to fix.
65        policy: String,
66        /// What the parser objected to.
67        message: String,
68    },
69}
70
71pub type Result<T> = std::result::Result<T, AmiError>;
72
73// Re-export helper functions and traits
74pub mod helpers;
75pub use helpers::OptionExt;
76
77// Re-export AmiError helper methods through the enum itself
78// The helper methods are implemented as extension methods on AmiError