Skip to main content

deltalake_core/
errors.rs

1//! Exceptions for the deltalake crate
2use chrono::{DateTime, Utc};
3use object_store::Error as ObjectStoreError;
4
5use crate::kernel::transaction::{CommitBuilderError, TransactionError};
6
7/// A result returned by delta-rs
8pub type DeltaResult<T, E = DeltaTableError> = Result<T, E>;
9
10/// Delta Table specific error
11#[allow(missing_docs)]
12#[derive(thiserror::Error, Debug)]
13pub enum DeltaTableError {
14    #[error("Kernel error: {0}")]
15    KernelError(#[from] delta_kernel::error::Error),
16
17    /// Error returned when reading the delta log object failed.
18    #[error("Failed to read delta log object: {}", .source)]
19    ObjectStore {
20        /// Storage error details when reading the delta log object failed.
21        #[from]
22        source: ObjectStoreError,
23    },
24
25    /// Error returned when parsing checkpoint parquet.
26    #[error("Failed to parse parquet: {}", .source)]
27    Parquet {
28        /// Parquet error details returned when reading the checkpoint failed.
29        #[from]
30        source: parquet::errors::ParquetError,
31    },
32
33    /// Error returned when converting the schema in Arrow format failed.
34    #[error("Failed to convert into Arrow schema: {}", .source)]
35    Arrow {
36        /// Arrow error details returned when converting the schema in Arrow format failed
37        #[from]
38        source: arrow::error::ArrowError,
39    },
40
41    /// Error returned when the log record has an invalid JSON.
42    #[error("Invalid JSON in log record, version={}, line=`{}`, err=`{}`", .version, .line, .json_err)]
43    InvalidJsonLog {
44        /// JSON error details returned when parsing the record JSON.
45        json_err: serde_json::error::Error,
46        /// invalid log entry content.
47        line: String,
48        /// corresponding table version for the log file.
49        version: i64,
50    },
51
52    /// Error returned when the log contains invalid stats JSON.
53    #[error("Invalid JSON in file stats: {}", .json_err)]
54    InvalidStatsJson {
55        /// JSON error details returned when parsing the stats JSON.
56        json_err: serde_json::error::Error,
57    },
58
59    /// Error returned when the DeltaTable has an invalid version.
60    #[error("Invalid table version: {0}")]
61    InvalidVersion(i64),
62
63    /// Error returned when the datetime string is invalid for a conversion.
64    #[error("Invalid datetime string: {}", .source)]
65    InvalidDateTimeString {
66        /// Parse error details returned of the datetime string parse error.
67        #[from]
68        source: chrono::ParseError,
69    },
70
71    /// Error returned when attempting to write bad data to the table
72    #[error("{message}")]
73    InvalidData {
74        /// Action error details returned of the invalid action.
75        message: String,
76    },
77
78    /// Error returned when it is not a DeltaTable.
79    #[error("Not a Delta table: {0}")]
80    NotATable(String),
81
82    /// Error returned when no schema was found in the DeltaTable.
83    #[error("No schema found, please make sure table is loaded.")]
84    NoSchema,
85
86    /// Error returned when writes are attempted with data that doesn't match the schema of the
87    /// table
88    #[error("Data does not match the schema or partitions of the table: {}", msg)]
89    SchemaMismatch {
90        /// Information about the mismatch
91        msg: String,
92    },
93
94    /// Error returned when a partition is not formatted as a Hive Partition.
95    #[error("This partition is not formatted with key=value: {}", .partition)]
96    PartitionError {
97        /// The malformed partition used.
98        partition: String,
99    },
100
101    /// Error returned when a invalid partition filter was found.
102    #[error("Invalid partition filter found: {}.", .partition_filter)]
103    InvalidPartitionFilter {
104        /// The invalid partition filter used.
105        partition_filter: String,
106    },
107
108    /// Error returned when a line from log record is invalid.
109    #[error("Failed to read line from log record")]
110    Io {
111        /// Source error details returned while reading the log record.
112        #[from]
113        source: std::io::Error,
114    },
115
116    /// Error raised while preparing a commit
117    #[error("Commit actions are unsound: {source}")]
118    CommitValidation {
119        /// The source error
120        source: CommitBuilderError,
121    },
122
123    /// Error raised while commititng transaction
124    #[error("Transaction failed: {source}")]
125    Transaction {
126        /// The source error
127        source: TransactionError,
128    },
129
130    /// Error returned when transaction is failed to be committed because given version already exists.
131    #[error("Delta transaction failed, version {0} already exists.")]
132    VersionAlreadyExists(i64),
133
134    /// Error returned when user attempts to commit actions that don't belong to the next version.
135    #[error("Delta transaction failed, version {0} does not follow {1}")]
136    VersionMismatch(i64, i64),
137
138    /// A Feature is missing to perform operation
139    #[error("Delta-rs must be build with feature '{feature}' to support loading from: {url}.")]
140    MissingFeature {
141        /// Name of the missing feature
142        feature: &'static str,
143        /// Storage location url
144        url: String,
145    },
146
147    /// A Feature is missing to perform operation
148    #[error("Cannot infer storage location from: {0}")]
149    InvalidTableLocation(String),
150
151    /// Generic Delta Table error
152    #[error("Log JSON serialization error: {json_err}")]
153    SerializeLogJson {
154        /// JSON serialization error
155        json_err: serde_json::error::Error,
156    },
157
158    /// Generic Delta Table error
159    #[error("Generic DeltaTable error: {0}")]
160    Generic(String),
161
162    /// Generic Delta Table error
163    #[error("Generic error: {source}")]
164    GenericError {
165        /// Source error
166        source: Box<dyn std::error::Error + Send + Sync + 'static>,
167    },
168
169    #[error("Kernel: {source}")]
170    Kernel {
171        #[from]
172        source: crate::kernel::Error,
173    },
174
175    #[error("Table metadata is invalid: {0}")]
176    MetadataError(String),
177
178    #[error("Table has not yet been initialized")]
179    NotInitialized,
180
181    #[error("Table has not yet been initialized with files, therefore {0} is not supported")]
182    NotInitializedWithFiles(String),
183
184    #[error("Change Data not enabled for version: {version}, Start: {start}, End: {end}")]
185    ChangeDataNotRecorded { version: i64, start: i64, end: i64 },
186
187    #[error("Reading a table version: {version} that does not have change data enabled")]
188    ChangeDataNotEnabled { version: i64 },
189
190    #[error("Invalid version. Start version {start} is greater than end version {end}")]
191    ChangeDataInvalidVersionRange { start: i64, end: i64 },
192
193    #[error("End timestamp {ending_timestamp} is greater than latest commit timestamp")]
194    ChangeDataTimestampGreaterThanCommit { ending_timestamp: DateTime<Utc> },
195
196    #[error("No starting version or timestamp provided for CDC")]
197    NoStartingVersionOrTimestamp,
198}
199
200impl From<object_store::path::Error> for DeltaTableError {
201    fn from(err: object_store::path::Error) -> Self {
202        Self::GenericError {
203            source: Box::new(err),
204        }
205    }
206}
207
208impl From<serde_json::Error> for DeltaTableError {
209    fn from(value: serde_json::Error) -> Self {
210        DeltaTableError::InvalidStatsJson { json_err: value }
211    }
212}
213
214impl DeltaTableError {
215    /// Crate a NotATable Error with message for given path.
216    pub fn not_a_table(path: impl AsRef<str>) -> Self {
217        let msg = format!(
218            "No snapshot or version 0 found, perhaps {} is an empty dir?",
219            path.as_ref()
220        );
221        Self::NotATable(msg)
222    }
223
224    /// Create a [Generic](DeltaTableError::Generic) error with the given message.
225    pub fn generic(msg: impl ToString) -> Self {
226        Self::Generic(msg.to_string())
227    }
228}