cli/
error.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::any::Any;
16
17use common_error::ext::{BoxedError, ErrorExt};
18use common_error::status_code::StatusCode;
19use common_macro::stack_trace_debug;
20use snafu::{Location, Snafu};
21
22#[derive(Snafu)]
23#[snafu(visibility(pub))]
24#[stack_trace_debug]
25pub enum Error {
26    #[snafu(display("Failed to install ring crypto provider: {}", msg))]
27    InitTlsProvider {
28        #[snafu(implicit)]
29        location: Location,
30        msg: String,
31    },
32    #[snafu(display("Failed to create default catalog and schema"))]
33    InitMetadata {
34        #[snafu(implicit)]
35        location: Location,
36        source: common_meta::error::Error,
37    },
38
39    #[snafu(display("Failed to init DDL manager"))]
40    InitDdlManager {
41        #[snafu(implicit)]
42        location: Location,
43        source: common_meta::error::Error,
44    },
45
46    #[snafu(display("Failed to init default timezone"))]
47    InitTimezone {
48        #[snafu(implicit)]
49        location: Location,
50        source: common_time::error::Error,
51    },
52
53    #[snafu(display("Failed to start procedure manager"))]
54    StartProcedureManager {
55        #[snafu(implicit)]
56        location: Location,
57        source: common_procedure::error::Error,
58    },
59
60    #[snafu(display("Failed to stop procedure manager"))]
61    StopProcedureManager {
62        #[snafu(implicit)]
63        location: Location,
64        source: common_procedure::error::Error,
65    },
66
67    #[snafu(display("Failed to start wal options allocator"))]
68    StartWalOptionsAllocator {
69        #[snafu(implicit)]
70        location: Location,
71        source: common_meta::error::Error,
72    },
73
74    #[snafu(display("Missing config, msg: {}", msg))]
75    MissingConfig {
76        msg: String,
77        #[snafu(implicit)]
78        location: Location,
79    },
80
81    #[snafu(display("Illegal config: {}", msg))]
82    IllegalConfig {
83        msg: String,
84        #[snafu(implicit)]
85        location: Location,
86    },
87
88    #[snafu(display("Failed to parse proxy options: {}", error))]
89    ParseProxyOpts {
90        #[snafu(source)]
91        error: reqwest::Error,
92        #[snafu(implicit)]
93        location: Location,
94    },
95
96    #[snafu(display("Failed to build reqwest client: {}", error))]
97    BuildClient {
98        #[snafu(implicit)]
99        location: Location,
100        #[snafu(source)]
101        error: reqwest::Error,
102    },
103
104    #[snafu(display("Failed to parse SQL: {}", sql))]
105    ParseSql {
106        sql: String,
107        #[snafu(implicit)]
108        location: Location,
109        source: query::error::Error,
110    },
111
112    #[snafu(display("Failed to plan statement"))]
113    PlanStatement {
114        #[snafu(implicit)]
115        location: Location,
116        source: query::error::Error,
117    },
118
119    #[snafu(display("Failed to load layered config"))]
120    LoadLayeredConfig {
121        #[snafu(source(from(common_config::error::Error, Box::new)))]
122        source: Box<common_config::error::Error>,
123        #[snafu(implicit)]
124        location: Location,
125    },
126
127    #[snafu(display("Failed to connect to Etcd at {etcd_addr}"))]
128    ConnectEtcd {
129        etcd_addr: String,
130        #[snafu(source)]
131        error: etcd_client::Error,
132        #[snafu(implicit)]
133        location: Location,
134    },
135
136    #[snafu(display("Failed to serde json"))]
137    SerdeJson {
138        #[snafu(source)]
139        error: serde_json::error::Error,
140        #[snafu(implicit)]
141        location: Location,
142    },
143
144    #[snafu(display("Failed to run http request: {reason}"))]
145    HttpQuerySql {
146        reason: String,
147        #[snafu(source)]
148        error: reqwest::Error,
149        #[snafu(implicit)]
150        location: Location,
151    },
152
153    #[snafu(display("Empty result from output"))]
154    EmptyResult {
155        #[snafu(implicit)]
156        location: Location,
157    },
158
159    #[snafu(display("Failed to manipulate file"))]
160    FileIo {
161        #[snafu(implicit)]
162        location: Location,
163        #[snafu(source)]
164        error: std::io::Error,
165    },
166
167    #[snafu(display("Failed to create directory {}", dir))]
168    CreateDir {
169        dir: String,
170        #[snafu(source)]
171        error: std::io::Error,
172    },
173
174    #[snafu(display("Failed to spawn thread"))]
175    SpawnThread {
176        #[snafu(source)]
177        error: std::io::Error,
178    },
179
180    #[snafu(display("Other error"))]
181    Other {
182        source: BoxedError,
183        #[snafu(implicit)]
184        location: Location,
185    },
186
187    #[snafu(display("Failed to build runtime"))]
188    BuildRuntime {
189        #[snafu(implicit)]
190        location: Location,
191        source: common_runtime::error::Error,
192    },
193
194    #[snafu(display("Failed to get cache from cache registry: {}", name))]
195    CacheRequired {
196        #[snafu(implicit)]
197        location: Location,
198        name: String,
199    },
200
201    #[snafu(display("Failed to build cache registry"))]
202    BuildCacheRegistry {
203        #[snafu(implicit)]
204        location: Location,
205        source: cache::error::Error,
206    },
207
208    #[snafu(display("Failed to initialize meta client"))]
209    MetaClientInit {
210        #[snafu(implicit)]
211        location: Location,
212        source: meta_client::error::Error,
213    },
214
215    #[snafu(display("Cannot find schema {schema} in catalog {catalog}"))]
216    SchemaNotFound {
217        catalog: String,
218        schema: String,
219        #[snafu(implicit)]
220        location: Location,
221    },
222
223    #[snafu(display("OpenDAL operator failed"))]
224    OpenDal {
225        #[snafu(implicit)]
226        location: Location,
227        #[snafu(source)]
228        error: opendal::Error,
229    },
230    #[snafu(display("S3 config need be set"))]
231    S3ConfigNotSet {
232        #[snafu(implicit)]
233        location: Location,
234    },
235    #[snafu(display("Output directory not set"))]
236    OutputDirNotSet {
237        #[snafu(implicit)]
238        location: Location,
239    },
240}
241
242pub type Result<T> = std::result::Result<T, Error>;
243
244impl ErrorExt for Error {
245    fn status_code(&self) -> StatusCode {
246        match self {
247            Error::InitMetadata { source, .. } | Error::InitDdlManager { source, .. } => {
248                source.status_code()
249            }
250
251            Error::MissingConfig { .. }
252            | Error::LoadLayeredConfig { .. }
253            | Error::IllegalConfig { .. }
254            | Error::InitTimezone { .. }
255            | Error::ConnectEtcd { .. }
256            | Error::CreateDir { .. }
257            | Error::EmptyResult { .. }
258            | Error::ParseProxyOpts { .. } => StatusCode::InvalidArguments,
259
260            Error::StartProcedureManager { source, .. }
261            | Error::StopProcedureManager { source, .. } => source.status_code(),
262            Error::StartWalOptionsAllocator { source, .. } => source.status_code(),
263            Error::HttpQuerySql { .. } => StatusCode::Internal,
264            Error::ParseSql { source, .. } | Error::PlanStatement { source, .. } => {
265                source.status_code()
266            }
267
268            Error::SerdeJson { .. }
269            | Error::FileIo { .. }
270            | Error::SpawnThread { .. }
271            | Error::InitTlsProvider { .. }
272            | Error::BuildClient { .. } => StatusCode::Unexpected,
273
274            Error::Other { source, .. } => source.status_code(),
275            Error::OpenDal { .. } => StatusCode::Internal,
276            Error::S3ConfigNotSet { .. } => StatusCode::InvalidArguments,
277            Error::OutputDirNotSet { .. } => StatusCode::InvalidArguments,
278
279            Error::BuildRuntime { source, .. } => source.status_code(),
280
281            Error::CacheRequired { .. } | Error::BuildCacheRegistry { .. } => StatusCode::Internal,
282            Error::MetaClientInit { source, .. } => source.status_code(),
283            Error::SchemaNotFound { .. } => StatusCode::DatabaseNotFound,
284        }
285    }
286
287    fn as_any(&self) -> &dyn Any {
288        self
289    }
290}