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 common_meta::peer::Peer;
21use object_store::Error as ObjectStoreError;
22use snafu::{Location, Snafu};
23use store_api::storage::TableId;
24
25#[derive(Snafu)]
26#[snafu(visibility(pub))]
27#[stack_trace_debug]
28pub enum Error {
29    #[snafu(display("Failed to install ring crypto provider: {}", msg))]
30    InitTlsProvider {
31        #[snafu(implicit)]
32        location: Location,
33        msg: String,
34    },
35
36    #[snafu(display("Failed to create default catalog and schema"))]
37    InitMetadata {
38        #[snafu(implicit)]
39        location: Location,
40        source: common_meta::error::Error,
41    },
42
43    #[snafu(display("Failed to init DDL manager"))]
44    InitDdlManager {
45        #[snafu(implicit)]
46        location: Location,
47        source: common_meta::error::Error,
48    },
49
50    #[snafu(display("Failed to init default timezone"))]
51    InitTimezone {
52        #[snafu(implicit)]
53        location: Location,
54        source: common_time::error::Error,
55    },
56
57    #[snafu(display("Failed to start procedure manager"))]
58    StartProcedureManager {
59        #[snafu(implicit)]
60        location: Location,
61        source: common_procedure::error::Error,
62    },
63
64    #[snafu(display("Failed to stop procedure manager"))]
65    StopProcedureManager {
66        #[snafu(implicit)]
67        location: Location,
68        source: common_procedure::error::Error,
69    },
70
71    #[snafu(display("Failed to start wal options allocator"))]
72    StartWalOptionsAllocator {
73        #[snafu(implicit)]
74        location: Location,
75        source: common_meta::error::Error,
76    },
77
78    #[snafu(display("Failed to get table metadata"))]
79    TableMetadata {
80        #[snafu(implicit)]
81        location: Location,
82        source: common_meta::error::Error,
83    },
84
85    #[snafu(display("Unexpected error: {}", msg))]
86    Unexpected {
87        msg: String,
88        #[snafu(implicit)]
89        location: Location,
90    },
91
92    #[snafu(display("Missing config, msg: {}", msg))]
93    MissingConfig {
94        msg: String,
95        #[snafu(implicit)]
96        location: Location,
97    },
98
99    #[snafu(display("Illegal config: {}", msg))]
100    IllegalConfig {
101        msg: String,
102        #[snafu(implicit)]
103        location: Location,
104    },
105
106    #[snafu(display("Failed to parse proxy options: {}", error))]
107    ParseProxyOpts {
108        #[snafu(source)]
109        error: reqwest::Error,
110        #[snafu(implicit)]
111        location: Location,
112    },
113
114    #[snafu(display("Failed to build reqwest client: {}", error))]
115    BuildClient {
116        #[snafu(implicit)]
117        location: Location,
118        #[snafu(source)]
119        error: reqwest::Error,
120    },
121
122    #[snafu(display("Failed to parse SQL: {}", sql))]
123    ParseSql {
124        sql: String,
125        #[snafu(implicit)]
126        location: Location,
127        source: query::error::Error,
128    },
129
130    #[snafu(display("Failed to plan statement"))]
131    PlanStatement {
132        #[snafu(implicit)]
133        location: Location,
134        source: query::error::Error,
135    },
136
137    #[snafu(display("Failed to load layered config"))]
138    LoadLayeredConfig {
139        #[snafu(source(from(common_config::error::Error, Box::new)))]
140        source: Box<common_config::error::Error>,
141        #[snafu(implicit)]
142        location: Location,
143    },
144
145    #[snafu(display("Failed to connect to Etcd at {etcd_addr}"))]
146    ConnectEtcd {
147        etcd_addr: String,
148        #[snafu(source)]
149        error: etcd_client::Error,
150        #[snafu(implicit)]
151        location: Location,
152    },
153
154    #[snafu(display("Failed to serde json"))]
155    SerdeJson {
156        #[snafu(source)]
157        error: serde_json::error::Error,
158        #[snafu(implicit)]
159        location: Location,
160    },
161
162    #[snafu(display("Failed to run http request: {reason}"))]
163    HttpQuerySql {
164        reason: String,
165        #[snafu(source)]
166        error: reqwest::Error,
167        #[snafu(implicit)]
168        location: Location,
169    },
170
171    #[snafu(display("Empty result from output"))]
172    EmptyResult {
173        #[snafu(implicit)]
174        location: Location,
175    },
176
177    #[snafu(display("Failed to manipulate file"))]
178    FileIo {
179        #[snafu(implicit)]
180        location: Location,
181        #[snafu(source)]
182        error: std::io::Error,
183    },
184
185    #[snafu(display("Failed to create directory {}", dir))]
186    CreateDir {
187        dir: String,
188        #[snafu(source)]
189        error: std::io::Error,
190    },
191
192    #[snafu(display("Failed to spawn thread"))]
193    SpawnThread {
194        #[snafu(source)]
195        error: std::io::Error,
196    },
197
198    #[snafu(display("Other error"))]
199    Other {
200        source: BoxedError,
201        #[snafu(implicit)]
202        location: Location,
203    },
204
205    #[snafu(display("Failed to build runtime"))]
206    BuildRuntime {
207        #[snafu(implicit)]
208        location: Location,
209        source: common_runtime::error::Error,
210    },
211
212    #[snafu(display("Failed to get cache from cache registry: {}", name))]
213    CacheRequired {
214        #[snafu(implicit)]
215        location: Location,
216        name: String,
217    },
218
219    #[snafu(display("Failed to build cache registry"))]
220    BuildCacheRegistry {
221        #[snafu(implicit)]
222        location: Location,
223        source: cache::error::Error,
224    },
225
226    #[snafu(display("Failed to initialize meta client"))]
227    MetaClientInit {
228        #[snafu(implicit)]
229        location: Location,
230        source: meta_client::error::Error,
231    },
232
233    #[snafu(display("Cannot find schema {schema} in catalog {catalog}"))]
234    SchemaNotFound {
235        catalog: String,
236        schema: String,
237        #[snafu(implicit)]
238        location: Location,
239    },
240
241    #[snafu(display("Table not found: {table_id}"))]
242    TableNotFound {
243        table_id: TableId,
244        #[snafu(implicit)]
245        location: Location,
246    },
247
248    #[snafu(display("OpenDAL operator failed"))]
249    OpenDal {
250        #[snafu(implicit)]
251        location: Location,
252        #[snafu(source)]
253        error: ObjectStoreError,
254    },
255
256    #[snafu(display("S3 config need be set"))]
257    S3ConfigNotSet {
258        #[snafu(implicit)]
259        location: Location,
260    },
261
262    #[snafu(display("Output directory not set"))]
263    OutputDirNotSet {
264        #[snafu(implicit)]
265        location: Location,
266    },
267
268    #[snafu(display("Empty store addresses"))]
269    EmptyStoreAddrs {
270        #[snafu(implicit)]
271        location: Location,
272    },
273
274    #[snafu(display("Unsupported memory backend"))]
275    UnsupportedMemoryBackend {
276        #[snafu(implicit)]
277        location: Location,
278    },
279
280    #[snafu(display("File path invalid: {}", msg))]
281    InvalidFilePath {
282        msg: String,
283        #[snafu(implicit)]
284        location: Location,
285    },
286
287    #[snafu(display("Invalid arguments: {}", msg))]
288    InvalidArguments {
289        msg: String,
290        #[snafu(implicit)]
291        location: Location,
292    },
293
294    #[snafu(display("Failed to init backend"))]
295    InitBackend {
296        #[snafu(implicit)]
297        location: Location,
298        #[snafu(source)]
299        error: ObjectStoreError,
300    },
301
302    #[snafu(display("Covert column schemas to defs failed"))]
303    CovertColumnSchemasToDefs {
304        #[snafu(implicit)]
305        location: Location,
306        source: operator::error::Error,
307    },
308
309    #[snafu(display("Failed to send request to datanode: {}", peer))]
310    SendRequestToDatanode {
311        peer: Peer,
312        #[snafu(implicit)]
313        location: Location,
314        source: common_meta::error::Error,
315    },
316}
317
318pub type Result<T> = std::result::Result<T, Error>;
319
320impl ErrorExt for Error {
321    fn status_code(&self) -> StatusCode {
322        match self {
323            Error::InitMetadata { source, .. }
324            | Error::InitDdlManager { source, .. }
325            | Error::TableMetadata { source, .. } => source.status_code(),
326
327            Error::MissingConfig { .. }
328            | Error::LoadLayeredConfig { .. }
329            | Error::IllegalConfig { .. }
330            | Error::InitTimezone { .. }
331            | Error::ConnectEtcd { .. }
332            | Error::CreateDir { .. }
333            | Error::EmptyResult { .. }
334            | Error::InvalidFilePath { .. }
335            | Error::UnsupportedMemoryBackend { .. }
336            | Error::InvalidArguments { .. }
337            | Error::ParseProxyOpts { .. } => StatusCode::InvalidArguments,
338
339            Error::CovertColumnSchemasToDefs { source, .. } => source.status_code(),
340            Error::SendRequestToDatanode { source, .. } => source.status_code(),
341
342            Error::StartProcedureManager { source, .. }
343            | Error::StopProcedureManager { source, .. } => source.status_code(),
344            Error::StartWalOptionsAllocator { source, .. } => source.status_code(),
345            Error::HttpQuerySql { .. } => StatusCode::Internal,
346            Error::ParseSql { source, .. } | Error::PlanStatement { source, .. } => {
347                source.status_code()
348            }
349            Error::Unexpected { .. } => StatusCode::Unexpected,
350
351            Error::SerdeJson { .. }
352            | Error::FileIo { .. }
353            | Error::SpawnThread { .. }
354            | Error::InitTlsProvider { .. }
355            | Error::BuildClient { .. } => StatusCode::Unexpected,
356
357            Error::Other { source, .. } => source.status_code(),
358            Error::OpenDal { .. } | Error::InitBackend { .. } => StatusCode::Internal,
359            Error::S3ConfigNotSet { .. }
360            | Error::OutputDirNotSet { .. }
361            | Error::EmptyStoreAddrs { .. } => StatusCode::InvalidArguments,
362
363            Error::BuildRuntime { source, .. } => source.status_code(),
364
365            Error::CacheRequired { .. } | Error::BuildCacheRegistry { .. } => StatusCode::Internal,
366            Error::MetaClientInit { source, .. } => source.status_code(),
367            Error::TableNotFound { .. } => StatusCode::TableNotFound,
368            Error::SchemaNotFound { .. } => StatusCode::DatabaseNotFound,
369        }
370    }
371
372    fn as_any(&self) -> &dyn Any {
373        self
374    }
375}