mz/
error.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! This module defines custom error types and structs related to MZ.
11//!
12//! [Error::ApiError] is an error struct that represents an error returned by the
13//! Materialize cloud API. It contains information about the HTTP status code and
14//! a vector of error messages.
15//!
16//! [`Error`](`enum@Error`) is a custom error type containing multiple variants
17//! for erros produced by the self crate, internal crates and external crates.
18
19use hyper::header::{InvalidHeaderValue, ToStrError};
20use thiserror::Error;
21use url::ParseError;
22
23/// A custom error type for `mz` extending the `Error` enums in
24/// the internal crates `mz-frontegg-auth`, `cloud-api` and
25/// `mz_frontegg_auth` and external crates like `serde_json`,
26/// `toml_edit`, `uuid`, `std::io` and `csv`.
27#[derive(Error, Debug)]
28pub enum Error {
29    /// An authentication error from the [`mz_frontegg_client`] crate.
30    #[error(transparent)]
31    AdminError(#[from] mz_frontegg_client::error::Error),
32    /// A Materialize Cloud API error from the [mz_cloud_api] crate.
33    #[error(transparent)]
34    ApiError(#[from] mz_cloud_api::error::Error),
35    /// A Frontegg authentication error.
36    #[error(transparent)]
37    AuthError(#[from] mz_frontegg_auth::Error),
38    /// Indicates an error parsing an endpoint.
39    #[error(
40        "Error parsing URL: {0}.\n\nTo resolve this issue, please verify the correctness of the URLs in the configuration file or the ones passed as parameters."
41    )]
42    UrlParseError(#[from] ParseError),
43    /// Error parsing (serializing/deserializing) a JSON.
44    #[error("Error parsing JSON: {0}")]
45    JsonParseError(#[from] serde_json::Error),
46    /// Error parsing (serializing/deserializing) a JSON using reqwest.
47    #[error("Error parsing request JSON: {0}")]
48    ReqwestJsonParseError(#[from] reqwest::Error),
49    /// Error parsing an App Password.
50    #[error(
51        "Error: {0}. \n\nTo resolve this issue, please verify the correctness of the app-password in the configuration file."
52    )]
53    AppPasswordParseError(#[from] mz_frontegg_auth::AppPasswordParseError),
54    /// Error indicating that a profile is missing the app-password.
55    #[error("Error: The current profile does not have an app-password.")]
56    AppPasswordMissing,
57    /// Error indicating that the profiles are missing in the config file.
58    #[error(
59        "Error: No profiles available in the configuration file. \n\nTo resolve this issue, you can add a new profile using the following command: `mz profile init`"
60    )]
61    ProfilesMissing,
62    /// Error indicating that the profile is missing in the config file.
63    #[error(
64        "Error: The profile '{0}' is missing in the configuration file. \n\nTo resolve this issue, you can either: \n1. Add the missing profile using the command `mz profile --profile {0} init` \n2. Set another existing profile using the command: `mz config set profile <profile_name>`."
65    )]
66    ProfileMissing(String),
67    /// Error finding the region's cloud provider.
68    #[error("Cloud region not found.")]
69    CloudRegionMissing,
70    /// Error parsing TOML.
71    #[error("Error parsing TOML file: {0}")]
72    TomlParseError(#[from] toml_edit::de::Error),
73    /// Error parsing TOML.
74    #[error("Error serializing the profile: {0}")]
75    TomlSerializingError(#[from] toml::ser::Error),
76    /// Error parsing TOML.
77    #[error(transparent)]
78    TomlError(#[from] toml_edit::TomlError),
79    /// Error parsing UUID.
80    #[error(transparent)]
81    UuidError(#[from] uuid::Error),
82    /// Error trying to execute a command.
83    #[error("Failed to execute command: {0}")]
84    CommandExecutionError(String),
85    /// Error when a command fails unexpectedly.
86    #[error("Command failed: {0}")]
87    CommandFailed(String),
88    /// I/O Error
89    #[error(transparent)]
90    IOError(#[from] std::io::Error),
91    /// I/O Error
92    #[error(transparent)]
93    CSVParseError(#[from] csv::Error),
94    /// Error that happens when a user cancels a login from the console UI.
95    #[error("Login canceled.")]
96    LoginOperationCanceled,
97    /// Error that raises when the clientid or secret are invalid.
98    /// It is a simpler alternative for parsing errors.
99    #[error("Invalid app-password.")]
100    InvalidAppPassword,
101    /// Error that raises when the region is enabled
102    /// but not ready yet.
103    #[error("The region is not ready yet.")]
104    NotReadyRegion,
105    /// Error that raises when the region is enabled
106    /// but not resolvable yet.
107    #[error("The region is not resolvable yet.")]
108    NotResolvableRegion,
109    /// Error that raises when a timeout is reached.
110    #[error("Timeout reached. Error: {0}")]
111    // It uses a Box<> to avoid recursion issues.
112    TimeoutError(Box<Error>),
113    /// Error that raises when the region is enabled and resolvable
114    /// but `pg_isready` fails
115    #[error("The region is not ready to accept SQL statements. `pg_isready` failed.")]
116    NotPgReadyError,
117    /// Error that raises when parsing semver.
118    #[error("Error parsing semver. Description: {0}")]
119    SemVerParseError(semver::Error),
120    /// Error that raises when trying to get the current
121    /// timestamp using `SystemTime::now().duration_since(UNIX_EPOCH)`
122    #[error("Error retrieving the current timestamp.")]
123    TimestampConversionError,
124    /// Error parsing a header for a request.
125    #[error("Error parsing header value: {0}")]
126    HeaderParseError(InvalidHeaderValue),
127    /// Error that raises when `dirs::cache_dir()` returns None.
128    #[error("Error. Cache dir not found")]
129    CacheDirNotFoundError,
130    /// Error that raises turning a Header value into str.
131    #[error("Error parsing a request header. Description: {0}")]
132    HeaderToStrError(ToStrError),
133    /// Error that raises when the request response
134    /// is invalid. Chances are that the request is not a 301.
135    #[error(
136        "Error the latest version header from the redirect request was not found. Verify the request is redirecting."
137    )]
138    LatestVersionHeaderMissingError,
139    /// Error that occurs when attempting to find the home directory.
140    #[error("An error occurred while trying to find the home directory.")]
141    HomeDirNotFoundError,
142    /// Error that raises when the security framework for macOS
143    /// to retrieve or set passwords to  the keychain fails.
144    #[error("Error using keychain. {0}")]
145    MacOsSecurityError(String),
146    /// Error that raises when the vault value from the config is invalid.
147    #[error("Vault value for the profile is invalid.")]
148    InvalidVaultError,
149    /// Error that raises when the user tries to create a new profile with a name that already exists.
150    #[error(
151        "The profile name '{0}' already exists. You can either use 'mz profile init -f' to replace it or 'mz profile init --profile <PROFILE>' to choose another name."
152    )]
153    ProfileNameAlreadyExistsError(String),
154}