1use std::backtrace::{Backtrace, BacktraceStatus};
4use std::convert::Infallible;
5use std::num::ParseIntError;
6use std::str::Utf8Error;
7
8#[cfg(feature = "default-engine-base")]
9use crate::arrow::error::ArrowError;
10#[cfg(feature = "default-engine-base")]
11use crate::object_store;
12use crate::schema::{DataType, StructType};
13use crate::table_properties::ParseIntervalError;
14use crate::Version;
15
16pub type DeltaResult<T, E = Error> = std::result::Result<T, E>;
18
19pub type DeltaResultIterator<'a, T> = Box<dyn Iterator<Item = DeltaResult<T>> + Send + 'a>;
24
25pub type DeltaResultIteratorStatic<T> = DeltaResultIterator<'static, T>;
28
29#[non_exhaustive]
31#[derive(thiserror::Error, Debug)]
32pub enum Error {
33 #[error("{source}\n{backtrace}")]
38 Backtraced {
39 source: Box<Self>,
40 backtrace: Box<Backtrace>,
41 },
42
43 #[cfg(feature = "default-engine-base")]
45 #[error(transparent)]
46 Arrow(ArrowError),
47
48 #[error("Error writing checkpoint: {0}")]
49 CheckpointWrite(String),
50
51 #[error("Invalid engine data type. Could not convert to {0}")]
53 EngineDataType(String),
54
55 #[error("Error extracting type {0}: {1}")]
57 Extract(&'static str, &'static str),
58
59 #[error("Generic delta kernel error: {0}")]
61 Generic(String),
62
63 #[error("Generic error: {source}")]
65 GenericError {
66 source: Box<dyn std::error::Error + Send + Sync + 'static>,
68 },
69
70 #[error(transparent)]
72 IOError(std::io::Error),
73
74 #[error("Internal error {0}. This is a kernel bug, please report.")]
76 InternalError(String),
77
78 #[cfg(feature = "default-engine-base")]
80 #[error("Arrow error: {0}")]
81 Parquet(#[from] crate::parquet::errors::ParquetError),
82
83 #[cfg(feature = "default-engine-base")]
87 #[error("Error interacting with object store: {0}")]
88 ObjectStore(object_store::Error),
89
90 #[cfg(feature = "default-engine-base")]
92 #[error("Object store path error: {0}")]
93 ObjectStorePath(#[from] object_store::path::Error),
94
95 #[cfg(feature = "default-engine-base")]
96 #[error("Reqwest Error: {0}")]
97 Reqwest(#[from] reqwest::Error),
98
99 #[error("File not found: {0}")]
101 FileNotFound(String),
102
103 #[error("{0}")]
105 MissingColumn(String),
106
107 #[error("Invalid partition values: {0}")]
110 InvalidPartitionValues(String),
111
112 #[error("Expected column type: {0}")]
114 UnexpectedColumnType(String),
115
116 #[error("Expected is missing: {0}")]
118 MissingData(String),
119
120 #[error("No table version found.")]
122 MissingVersion,
123
124 #[error("Deletion Vector error: {0}")]
126 DeletionVector(String),
127
128 #[error("Selection vector is larger than data length: {0}")]
130 InvalidSelectionVector(String),
131
132 #[error("Invalid transaction state: {0}")]
134 InvalidTransactionState(String),
135
136 #[error("Invalid url: {0}")]
138 InvalidUrl(#[from] url::ParseError),
139
140 #[error(transparent)]
142 MalformedJson(serde_json::Error),
143
144 #[error("No table metadata found in delta log.")]
146 MissingMetadata,
147
148 #[error("No protocol found in delta log.")]
150 MissingProtocol,
151
152 #[error("Invalid protocol action in the delta log: {0}")]
154 InvalidProtocol(String),
155
156 #[error("No table metadata or protocol found in delta log.")]
158 MissingMetadataAndProtocol,
159
160 #[error("Failed to parse value '{0}' as '{1}'")]
162 ParseError(String, DataType),
163
164 #[error("Join failure: {0}")]
166 JoinFailure(String),
167
168 #[error("Could not convert to string from utf-8: {0}")]
170 Utf8Error(#[from] Utf8Error),
171
172 #[error("Could not parse int: {0}")]
174 ParseIntError(#[from] ParseIntError),
175
176 #[error("Invalid column mapping mode: {0}")]
177 InvalidColumnMappingMode(String),
178
179 #[error("Invalid table location: {0}.")]
181 InvalidTableLocation(String),
182
183 #[error("Invalid decimal: {0}")]
185 InvalidDecimal(String),
186
187 #[error("Invalid struct data: {0}")]
189 InvalidStructData(String),
190
191 #[error("Invalid expression evaluation: {0}")]
193 InvalidExpressionEvaluation(String),
194
195 #[error("Invalid log path: {0}")]
197 InvalidLogPath(String),
198
199 #[error("File already exists: {0}")]
201 FileAlreadyExists(String),
202
203 #[error("Unsupported: {0}")]
205 Unsupported(String),
206
207 #[error("Checksum write unsupported: {0}")]
209 ChecksumWriteUnsupported(String),
210
211 #[error(transparent)]
213 ParseIntervalError(#[from] ParseIntervalError),
214
215 #[error("Change data feed is unsupported for the table at version {0}")]
216 ChangeDataFeedUnsupported(Version),
217
218 #[error("Change data feed encountered incompatible schema. Expected {0}, got {1}")]
219 ChangeDataFeedIncompatibleSchema(String, String),
220
221 #[error("Invalid Checkpoint: {0}")]
223 InvalidCheckpoint(String),
224
225 #[error(transparent)]
227 LiteralExpressionTransformError(
228 #[from] crate::expressions::literal_expression_transform::Error,
229 ),
230
231 #[error("Schema error: {0}")]
233 Schema(String),
234
235 #[error("Stats validation error: {0}")]
237 StatsValidation(String),
238
239 #[error(transparent)]
241 LogHistory(#[from] Box<crate::history_manager::error::LogHistoryError>),
242
243 #[cfg(feature = "declarative-plans")]
244 #[error("Declarative plan execution yielded the incorrect type: expected PlanResult::{expected}, got PlanResult::{actual}")]
245 PlanResultTypeMismatch {
246 expected: &'static str,
247 actual: &'static str,
248 },
249}
250
251impl Error {
253 pub(crate) fn checkpoint_write(msg: impl ToString) -> Self {
254 Self::CheckpointWrite(msg.to_string())
255 }
256
257 pub fn generic_err(source: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> Self {
258 Self::GenericError {
259 source: source.into(),
260 }
261 }
262 pub fn generic(msg: impl ToString) -> Self {
263 Self::Generic(msg.to_string())
264 }
265 pub fn file_not_found(path: impl ToString) -> Self {
266 Self::FileNotFound(path.to_string())
267 }
268 pub fn missing_column(name: impl ToString) -> Self {
269 Self::MissingColumn(name.to_string()).with_backtrace()
270 }
271 pub fn unexpected_column_type(name: impl ToString) -> Self {
272 Self::UnexpectedColumnType(name.to_string())
273 }
274 pub fn invalid_partition_values(msg: impl ToString) -> Self {
275 Self::InvalidPartitionValues(msg.to_string())
276 }
277 pub fn missing_data(name: impl ToString) -> Self {
278 Self::MissingData(name.to_string())
279 }
280 pub fn deletion_vector(msg: impl ToString) -> Self {
281 Self::DeletionVector(msg.to_string())
282 }
283 pub fn engine_data_type(msg: impl ToString) -> Self {
284 Self::EngineDataType(msg.to_string())
285 }
286 pub fn join_failure(msg: impl ToString) -> Self {
287 Self::JoinFailure(msg.to_string())
288 }
289 pub fn invalid_table_location(location: impl ToString) -> Self {
290 Self::InvalidTableLocation(location.to_string())
291 }
292 pub fn invalid_column_mapping_mode(mode: impl ToString) -> Self {
293 Self::InvalidColumnMappingMode(mode.to_string())
294 }
295 pub fn invalid_decimal(msg: impl ToString) -> Self {
296 Self::InvalidDecimal(msg.to_string())
297 }
298 pub fn invalid_struct_data(msg: impl ToString) -> Self {
299 Self::InvalidStructData(msg.to_string())
300 }
301 pub fn invalid_expression(msg: impl ToString) -> Self {
302 Self::InvalidExpressionEvaluation(msg.to_string())
303 }
304 pub(crate) fn invalid_log_path(msg: impl ToString) -> Self {
305 Self::InvalidLogPath(msg.to_string())
306 }
307
308 pub fn internal_error(msg: impl ToString) -> Self {
309 Self::InternalError(msg.to_string()).with_backtrace()
310 }
311
312 pub fn invalid_protocol(msg: impl ToString) -> Self {
313 Self::InvalidProtocol(msg.to_string())
314 }
315
316 pub fn invalid_transaction_state(msg: impl ToString) -> Self {
317 Self::InvalidTransactionState(msg.to_string())
318 }
319
320 pub fn unsupported(msg: impl ToString) -> Self {
321 Self::Unsupported(msg.to_string())
322 }
323 pub fn change_data_feed_unsupported(version: impl Into<Version>) -> Self {
324 Self::ChangeDataFeedUnsupported(version.into())
325 }
326 pub(crate) fn change_data_feed_incompatible_schema(
327 expected: &StructType,
328 actual: &StructType,
329 ) -> Self {
330 Self::ChangeDataFeedIncompatibleSchema(format!("{expected:?}"), format!("{actual:?}"))
331 }
332
333 pub fn invalid_checkpoint(msg: impl ToString) -> Self {
334 Self::InvalidCheckpoint(msg.to_string())
335 }
336
337 pub fn schema(msg: impl ToString) -> Self {
338 Self::Schema(msg.to_string())
339 }
340
341 pub fn stats_validation(msg: impl ToString) -> Self {
342 Self::StatsValidation(msg.to_string())
343 }
344
345 #[cfg(feature = "declarative-plans")]
346 pub fn plan_result_type_mismatch(expected: &'static str, actual: &'static str) -> Self {
347 Self::PlanResultTypeMismatch { expected, actual }
348 }
349
350 #[must_use]
352 pub fn with_backtrace(self) -> Self {
353 let backtrace = Backtrace::capture();
354 match backtrace.status() {
355 BacktraceStatus::Captured => Self::Backtraced {
356 source: Box::new(self),
357 backtrace: Box::new(backtrace),
358 },
359 _ => self,
360 }
361 }
362}
363
364macro_rules! from_with_backtrace(
365 ( $(($error_type: ty, $error_variant: ident)), * ) => {
366 $(
367 impl From<$error_type> for Error {
368 fn from(value: $error_type) -> Self {
369 Self::$error_variant(value).with_backtrace()
370 }
371 }
372 )*
373 };
374);
375
376from_with_backtrace!(
377 (serde_json::Error, MalformedJson),
378 (std::io::Error, IOError)
379);
380
381#[cfg(feature = "default-engine-base")]
382impl From<ArrowError> for Error {
383 fn from(value: ArrowError) -> Self {
384 Self::Arrow(value).with_backtrace()
385 }
386}
387
388#[cfg(feature = "default-engine-base")]
389impl From<object_store::Error> for Error {
390 fn from(value: object_store::Error) -> Self {
391 match value {
392 object_store::Error::NotFound { path, .. } => Self::file_not_found(path),
393 err => Self::ObjectStore(err),
394 }
395 }
396}
397
398impl From<Infallible> for Error {
403 fn from(value: Infallible) -> Self {
404 match value {}
405 }
406}