Skip to main content

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 std::path::PathBuf;
20
21use hyper::header::{InvalidHeaderValue, ToStrError};
22use thiserror::Error;
23use url::ParseError;
24
25/// A custom error type for `mz` extending the `Error` enums in
26/// the internal crates `mz-frontegg-auth`, `cloud-api` and
27/// `mz_frontegg_auth` and external crates like `serde_json`,
28/// `toml_edit`, `uuid`, `std::io` and `csv`.
29#[derive(Error, Debug)]
30pub enum Error {
31    /// An authentication error from the [`mz_frontegg_client`] crate.
32    #[error(transparent)]
33    AdminError(#[from] mz_frontegg_client::error::Error),
34    /// A Materialize Cloud API error from the [mz_cloud_api] crate.
35    #[error(transparent)]
36    ApiError(#[from] mz_cloud_api::error::Error),
37    /// A Frontegg authentication error.
38    #[error(transparent)]
39    AuthError(#[from] mz_frontegg_auth::Error),
40    /// Indicates an error parsing an endpoint.
41    #[error(
42        "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."
43    )]
44    UrlParseError(#[from] ParseError),
45    /// Error parsing (serializing/deserializing) a JSON.
46    #[error("Error parsing JSON: {0}")]
47    JsonParseError(#[from] serde_json::Error),
48    /// Error parsing (serializing/deserializing) a JSON using reqwest.
49    #[error("Error parsing request JSON: {0}")]
50    ReqwestJsonParseError(#[from] reqwest::Error),
51    /// Error parsing an App Password.
52    #[error(
53        "Error: {0}. \n\nTo resolve this issue, please verify the correctness of the app-password in the configuration file."
54    )]
55    AppPasswordParseError(#[from] mz_frontegg_auth::AppPasswordParseError),
56    /// Error indicating that a profile is missing the app-password.
57    #[error("Error: The current profile does not have an app-password.")]
58    AppPasswordMissing,
59    /// Error indicating that the profiles are missing in the config file.
60    #[error(
61        "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`"
62    )]
63    ProfilesMissing,
64    /// Error indicating that the profile is missing in the config file.
65    #[error(
66        "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>`."
67    )]
68    ProfileMissing(String),
69    /// Error finding the region's cloud provider.
70    #[error("Cloud region not found.")]
71    CloudRegionMissing,
72    /// Error parsing TOML.
73    #[error("Error parsing TOML file: {0}")]
74    TomlParseError(#[from] toml_edit::de::Error),
75    /// Error parsing TOML.
76    #[error("Error serializing the profile: {0}")]
77    TomlSerializingError(#[from] toml::ser::Error),
78    /// Error parsing TOML.
79    #[error(transparent)]
80    TomlError(#[from] toml_edit::TomlError),
81    /// Error parsing UUID.
82    #[error(transparent)]
83    UuidError(#[from] uuid::Error),
84    /// Error trying to execute a command.
85    #[error("Failed to execute command: {0}")]
86    CommandExecutionError(String),
87    /// Error when a command fails unexpectedly.
88    #[error("Command failed: {0}")]
89    CommandFailed(String),
90    /// I/O Error
91    #[error(transparent)]
92    IOError(#[from] std::io::Error),
93    /// Error raised when the configuration file exists but cannot be written.
94    #[error("Error: The configuration file {0} is not writable: {1}")]
95    ConfigFileNotWritable(PathBuf, #[source] std::io::Error),
96    /// I/O Error
97    #[error(transparent)]
98    CSVParseError(#[from] csv::Error),
99    /// Error that happens when a user cancels a login from the console UI.
100    #[error("Login canceled.")]
101    LoginOperationCanceled,
102    /// Error that raises when the clientid or secret are invalid.
103    /// It is a simpler alternative for parsing errors.
104    #[error("Invalid app-password.")]
105    InvalidAppPassword,
106    /// Error that raises when the region is enabled
107    /// but not ready yet.
108    #[error("The region is not ready yet.")]
109    NotReadyRegion,
110    /// Error that raises when the region is enabled
111    /// but not resolvable yet.
112    #[error("The region is not resolvable yet.")]
113    NotResolvableRegion,
114    /// Error that raises when a timeout is reached.
115    #[error("Timeout reached. Error: {0}")]
116    // It uses a Box<> to avoid recursion issues.
117    TimeoutError(Box<Error>),
118    /// Error that raises when the region is enabled and resolvable
119    /// but `pg_isready` fails
120    #[error("The region is not ready to accept SQL statements. `pg_isready` failed.")]
121    NotPgReadyError,
122    /// Error that raises when parsing semver.
123    #[error("Error parsing semver. Description: {0}")]
124    SemVerParseError(semver::Error),
125    /// Error that raises when trying to get the current
126    /// timestamp using `SystemTime::now().duration_since(UNIX_EPOCH)`
127    #[error("Error retrieving the current timestamp.")]
128    TimestampConversionError,
129    /// Error parsing a header for a request.
130    #[error("Error parsing header value: {0}")]
131    HeaderParseError(InvalidHeaderValue),
132    /// Error that raises when `dirs::cache_dir()` returns None.
133    #[error("Error. Cache dir not found")]
134    CacheDirNotFoundError,
135    /// Error that raises turning a Header value into str.
136    #[error("Error parsing a request header. Description: {0}")]
137    HeaderToStrError(ToStrError),
138    /// Error that raises when the request response
139    /// is invalid. Chances are that the request is not a 301.
140    #[error(
141        "Error the latest version header from the redirect request was not found. Verify the request is redirecting."
142    )]
143    LatestVersionHeaderMissingError,
144    /// Error that occurs when attempting to find the home directory.
145    #[error("An error occurred while trying to find the home directory.")]
146    HomeDirNotFoundError,
147    /// Error that raises when the security framework for macOS
148    /// to retrieve or set passwords to  the keychain fails.
149    #[error("Error using keychain. {0}")]
150    MacOsSecurityError(String),
151    /// Error that raises when the vault value from the config is invalid.
152    #[error("Vault value for the profile is invalid.")]
153    InvalidVaultError,
154    /// Error that raises when the user tries to create a new profile with a name that already exists.
155    #[error(
156        "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."
157    )]
158    ProfileNameAlreadyExistsError(String),
159    /// Error that raises when a secret value does not parse as a single SQL expression.
160    #[error("Invalid secret expression: {0}")]
161    InvalidSecretExpression(String),
162}