1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
use std::fmt;
use query_planning::error::QueryErrorCode;
/// Declares [`ErrorCode`] from one list: each variant with its report label,
/// [`ErrorKind`], and [`ErrorStatus`]. Every table derives from the list, so a
/// new code cannot ship without all three.
macro_rules! error_codes {
($($(#[$doc:meta])* $code:ident => $label:literal, $kind:ident, $status:ident;)+) => {
/// Stable, machine-readable adapter error codes.
///
/// Codes describe the closest adapter-level cause. [`ErrorKind`] and
/// [`ErrorStatus`] are derived from the code by [`ErrorCode::kind`]
/// and [`ErrorCode::status`]. Consumers should treat those methods as
/// the policy contract and should not infer behavior from variant
/// names.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ErrorCode {
$($(#[$doc])* $code,)+
}
impl ErrorCode {
/// Every adapter error code, in declaration order.
pub const ALL: &'static [Self] = &[$(Self::$code),+];
/// Stable snake-case code label used in reports and error text.
pub const fn as_str(self) -> &'static str {
match self {
$(Self::$code => $label,)+
}
}
/// Stable coarse category of this code.
///
/// `kind` is the broad bucket used for diagnostics and
/// aggregation. It is less specific than [`ErrorCode`] and stays
/// stable for consumers that group failures without depending on
/// every code variant.
pub const fn kind(self) -> ErrorKind {
match self {
$(Self::$code => ErrorKind::$kind,)+
}
}
/// Retry/remediation status of this code.
///
/// Attempt retry advice is derived only after terminal evidence is
/// sealed. [`ErrorStatus::Persistent`] means a repeated or
/// known-continuing dependency failure that requires escalation or
/// intervention, while [`ErrorStatus::Permanent`] means the
/// request, input, configuration, or code must change before the
/// same operation can succeed.
pub const fn status(self) -> ErrorStatus {
match self {
$(Self::$code => ErrorStatus::$status,)+
}
}
}
};
}
error_codes! {
/// Query execution was canceled by the caller.
Cancelled => "cancelled", Cancelled, Permanent;
/// SQL text could not be parsed.
SqlParse => "sql_parse", InvalidInput, Permanent;
/// The server request envelope or handle was invalid for the operation.
InvalidRequest => "invalid_request", InvalidInput, Permanent;
/// A server, backend, or device configuration value is invalid or
/// inconsistent with the discovered hardware.
///
/// The same configuration fails again until it changes; the message names
/// the setting, its value, and the largest accepted value when one exists.
InvalidConfiguration => "invalid_configuration", InvalidInput, Permanent;
/// DataFusion rejected the query during logical or physical planning.
DataFusionPlanning => "datafusion_planning", Planning, Permanent;
/// Adapter-owned planning exceeded its configured time budget.
///
/// This is classified as permanent for the same request and budget: retry
/// with table maintenance, a narrower request, or a larger configured
/// planning budget.
PlanningTimeout => "planning_timeout", Planning, Permanent;
/// A requested catalog, schema, table, table function, or similar named object was not found.
ObjectNotFound => "object_not_found", NotFound, Permanent;
/// Source object storage denied access to the requested object or metadata.
SourceAccessDenied => "source_access_denied", PermissionDenied, Permanent;
/// Source object storage lacked valid authentication credentials.
SourceUnauthenticated => "source_unauthenticated", Unauthenticated, Permanent;
/// Source object storage could not find the requested object.
SourceObjectNotFound => "source_object_not_found", NotFound, Permanent;
/// Source object storage failed with a retryable transport or service error.
SourceTemporaryFailure => "source_temporary_failure", DependencyFailure, Temporary;
/// A source reader or source dependency failed permanently while serving the request.
SourceDependencyFailure => "source_dependency_failure", DependencyFailure, Permanent;
/// A named field was not present in a resolved schema.
FieldNotFound => "field_not_found", InvalidInput, Permanent;
/// Materialized graph edges or side inputs violate the graph operation's
/// declared input contract.
GraphInputInvalid => "graph_input_invalid", InvalidInput, Permanent;
/// A completed-plan requirement needed a GPU operation that the exact
/// final physical plan could not provide.
RequiredGpuOperationUnsupported => "required_gpu_operation_unsupported", Unsupported, Permanent;
/// The exact completed physical plan did not satisfy a configured final
/// plan requirement.
FinalPlanRequirementUnsatisfied => "final_plan_requirement_unsatisfied", Planning, Permanent;
/// A physical operator is unsupported by the GPU/native adapter path.
UnsupportedOperator => "unsupported_operator", Unsupported, Permanent;
/// A physical expression or expression form is unsupported.
UnsupportedExpression => "unsupported_expression", Unsupported, Permanent;
/// A data type, physical representation, or type combination is unsupported.
UnsupportedType => "unsupported_type", Unsupported, Permanent;
/// A DataFusion physical plan is invalid for the adapter boundary.
///
/// Use this only for malformed or inconsistent plans. A well-formed plan
/// outside the supported capability catalogue is reported as unsupported.
InvalidExecutionPlan => "invalid_execution_plan", Planning, Permanent;
/// An execution plan had an impossible child count for the adapter node.
InvalidChildCount => "invalid_child_count", Internal, Permanent;
/// cuDF rejected an input, including permanent `NotFound` conditions.
CudfInvalidInput => "cudf_invalid_input", InvalidInput, Permanent;
/// cuDF reported a permanent unsupported capability.
CudfUnsupported => "cudf_unsupported", Unsupported, Permanent;
/// A host materialization size computation overflowed the platform range.
SizeOverflow => "size_overflow", ResourceExhausted, Permanent;
/// One unsplittable Arrow host row exceeds the configured deterministic
/// materialization ceiling.
HostMaterializationLimitExceeded => "host_materialization_limit_exceeded", ResourceExhausted, Permanent;
/// A bounded host-staging boundary exceeded its configured cumulative byte
/// ceiling before GPU admission or a device-to-host copy.
HostStagingLimitExceeded => "host_staging_limit_exceeded", ResourceExhausted, Permanent;
/// DataFusion's host memory pool rejected a reservation.
///
/// Represents a temporary resource exhaustion in the host-side pool.
/// Device memory is governed by the query domain allocator and reports
/// through [`Self::QueryMemoryLimitExceeded`], [`Self::DeviceOutOfMemory`],
/// and [`Self::DeviceAllocationFailed`].
HostMemoryExhausted => "host_memory_exhausted", ResourceExhausted, Temporary;
/// cuDF reported a temporary dependency/runtime failure.
CudfTemporaryFailure => "cudf_temporary_failure", DependencyFailure, Temporary;
/// cuDF reported a persistent dependency/runtime failure.
///
/// The failure has been observed to recur or is known to continue. Stop
/// automatic retries and escalate or wait for intervention.
CudfPersistentFailure => "cudf_persistent_failure", DependencyFailure, Persistent;
/// cuDF reported a permanent dependency failure.
CudfDependencyFailure => "cudf_dependency_failure", DependencyFailure, Permanent;
/// An iterative native algorithm reached its configured iteration bound.
AlgorithmDidNotConverge => "algorithm_did_not_converge", DependencyFailure, Permanent;
/// cuDF reported an invariant or execution-context violation.
CudfInvariantViolation => "cudf_invariant_violation", InvariantViolation, Permanent;
/// The native admission controller could not reserve requested memory.
///
/// Represents a temporary resource condition propagated from native
/// execution, separate from a cuDF allocator failure.
MemoryReservationFailed => "memory_reservation_failed", ResourceExhausted, Temporary;
/// The native query service rejected work because admission capacity was exhausted.
ServiceOverloaded => "service_overloaded", ResourceExhausted, Temporary;
/// The requested query cap cannot fit on any eligible device after
/// subtracting resident ownership.
QueryBudgetUnavailable => "query_budget_unavailable", ResourceExhausted, Temporary;
/// The query domain rejected an actual or exact-required allocation over
/// the query's fixed memory cap.
QueryMemoryLimitExceeded => "query_memory_limit_exceeded", ResourceExhausted, Permanent;
/// A device allocation failed with confirmed physical-memory provenance.
DeviceOutOfMemory => "device_out_of_memory", ResourceExhausted, Temporary;
/// A device allocation failed without confirmed physical-memory provenance.
DeviceAllocationFailed => "device_allocation_failed", ResourceExhausted, Temporary;
/// A persistent device or CUDA runtime fault made the affected device
/// unavailable.
DeviceFault => "device_fault", DependencyFailure, Persistent;
/// Cleanup or synchronization could not establish safe release of the
/// attempt's device resources.
CleanupFailed => "cleanup_failed", DependencyFailure, Persistent;
/// An owner, provenance, ledger, or stream-routing invariant was violated.
InternalInvariantViolation => "internal_invariant_violation", InvariantViolation, Permanent;
/// One logical Arrow row cannot be represented within the configured
/// Flight/gRPC message limit.
///
/// This is permanent for the same row and transport limit: callers must
/// project a smaller value or otherwise change the request. The server
/// must not raise tonic's message-size limit to hide this condition.
FlightFrameTooLarge => "flight_frame_too_large", ResourceExhausted, Permanent;
/// The Flight SQL server transport failed outside request handling.
ServerTransportFailure => "server_transport_failure", DependencyFailure, Permanent;
/// An internal adapter bug or unreachable condition.
Internal => "internal", Internal, Permanent;
}
impl fmt::Display for ErrorCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
/// Coarse adapter error category.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ErrorKind {
/// Caller-requested cancellation stopped execution.
Cancelled,
/// Requested catalog, schema, table, table function, or similar named object was not found.
NotFound,
/// The caller or configured source credentials do not have permission.
PermissionDenied,
/// The caller or configured source credentials are not authenticated.
Unauthenticated,
/// Planning, validation, or physical-plan construction failure.
Planning,
/// Caller-provided input is invalid for the requested operation.
InvalidInput,
/// Requested operator, expression, type, or native shape is unsupported.
Unsupported,
/// Runtime execution failure at the adapter boundary.
Execution,
/// Memory or another bounded resource was exhausted or could not be reserved.
ResourceExhausted,
/// cuDF or another dependency failed outside resource-exhaustion handling.
DependencyFailure,
/// An adapter or cuDF invariant was violated.
InvariantViolation,
/// Internal bug or unreachable condition.
Internal,
}
impl ErrorKind {
/// Stable snake-case category label used in reports and error text.
pub const fn as_str(self) -> &'static str {
match self {
Self::Cancelled => "cancelled",
Self::NotFound => "not_found",
Self::PermissionDenied => "permission_denied",
Self::Unauthenticated => "unauthenticated",
Self::Planning => "planning",
Self::InvalidInput => "invalid_input",
Self::Unsupported => "unsupported",
Self::Execution => "execution",
Self::ResourceExhausted => "resource_exhausted",
Self::DependencyFailure => "dependency_failure",
Self::InvariantViolation => "invariant_violation",
Self::Internal => "internal",
}
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
/// Retry and remediation status for adapter errors.
///
/// Provides coarse source classification. Attempt retry advice is derived only
/// after terminal evidence is sealed.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ErrorStatus {
/// The same request will not succeed without changing its query, input,
/// configuration, or code. Do not retry it automatically.
Permanent,
/// The failure may clear without external repair. A sealed attempt report
/// still needs terminal evidence before it can advise backoff or retry.
Temporary,
/// A dependency/runtime failure has been observed to recur or is known to
/// continue. Stop automatic retries and escalate or wait for intervention.
///
/// This remains distinct from [`Self::Permanent`] because it records a
/// continuing dependency failure, while `Permanent` records a request that
/// must change. Neither status alone is retry advice.
Persistent,
}
impl ErrorStatus {
/// Stable snake-case status label used in reports and error text.
pub const fn as_str(self) -> &'static str {
match self {
Self::Permanent => "permanent",
Self::Temporary => "temporary",
Self::Persistent => "persistent",
}
}
}
impl fmt::Display for ErrorStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
/// Maps a native engine error code to the closest adapter code.
///
/// The mapping is lossy at the top-level code: native
/// `UnsupportedPipelineContract` becomes adapter `UnsupportedOperator` because
/// the adapter has no pipeline-contract code. The exact native code remains
/// available in the `native_code` fact attached by `Error::from_native`.
pub(crate) fn code_for_native_error(code: QueryErrorCode) -> ErrorCode {
match code {
QueryErrorCode::Cancelled => ErrorCode::Cancelled,
QueryErrorCode::UnsupportedPipelineContract => ErrorCode::UnsupportedOperator,
QueryErrorCode::UnsupportedOperator => ErrorCode::UnsupportedOperator,
QueryErrorCode::UnsupportedExpression => ErrorCode::UnsupportedExpression,
QueryErrorCode::UnsupportedType => ErrorCode::UnsupportedType,
QueryErrorCode::InvalidPlan => ErrorCode::InvalidExecutionPlan,
QueryErrorCode::InvalidAttemptCorrelation => ErrorCode::InvalidRequest,
QueryErrorCode::InvalidConfiguration => ErrorCode::InvalidConfiguration,
QueryErrorCode::GraphInputInvalid => ErrorCode::GraphInputInvalid,
QueryErrorCode::CudfInvalidInput => ErrorCode::CudfInvalidInput,
QueryErrorCode::CudfUnsupported => ErrorCode::CudfUnsupported,
QueryErrorCode::SizeOverflow => ErrorCode::SizeOverflow,
QueryErrorCode::HostMaterializationLimitExceeded => ErrorCode::HostMaterializationLimitExceeded,
QueryErrorCode::CudfTemporaryFailure => ErrorCode::CudfTemporaryFailure,
QueryErrorCode::CudfPersistentFailure => ErrorCode::CudfPersistentFailure,
QueryErrorCode::CudfDependencyFailure => ErrorCode::CudfDependencyFailure,
QueryErrorCode::AlgorithmDidNotConverge => ErrorCode::AlgorithmDidNotConverge,
QueryErrorCode::SourceAccessDenied => ErrorCode::SourceAccessDenied,
QueryErrorCode::SourceUnauthenticated => ErrorCode::SourceUnauthenticated,
QueryErrorCode::SourceObjectNotFound => ErrorCode::SourceObjectNotFound,
QueryErrorCode::SourceTemporaryFailure => ErrorCode::SourceTemporaryFailure,
QueryErrorCode::CudfInvariantViolation => ErrorCode::CudfInvariantViolation,
QueryErrorCode::MemoryReservationFailed => ErrorCode::MemoryReservationFailed,
QueryErrorCode::ServiceOverloaded => ErrorCode::ServiceOverloaded,
QueryErrorCode::QueryBudgetUnavailable => ErrorCode::QueryBudgetUnavailable,
QueryErrorCode::QueryMemoryLimitExceeded => ErrorCode::QueryMemoryLimitExceeded,
QueryErrorCode::DeviceOutOfMemory => ErrorCode::DeviceOutOfMemory,
QueryErrorCode::DeviceAllocationFailed => ErrorCode::DeviceAllocationFailed,
QueryErrorCode::DeviceFault => ErrorCode::DeviceFault,
QueryErrorCode::CleanupFailed => ErrorCode::CleanupFailed,
QueryErrorCode::InternalInvariantViolation => ErrorCode::InternalInvariantViolation,
QueryErrorCode::Internal => ErrorCode::Internal,
}
}