crates/graphar-flight/src/error.rs
use thiserror::Error;
pub type Result<T> = std::result::Result<T, FlightSqlError>;
#[derive(Debug, Error)]
pub enum FlightSqlError {
#[error("Redis error: {0}")]
Redis(#[from] redis::RedisError),
#[error("Arrow error: {0}")]
Arrow(#[from] arrow::error::ArrowError),
#[error("Arrow Flight error: {0}")]
Flight(#[from] arrow_flight::error::FlightError),
#[error("FalkorDB error: {0}")]
Falkor(#[from] graphar_falkordb::FalkorError),
#[error("GraphAr error: {0}")]
Graphar(#[from] graphar::GraphArError),
#[error("Iceberg/skade error: {0}")]
Skade(String),
#[error("Schema not registered for key '{0}' — call SchemaRegistry::register first")]
UnregisteredSchema(String),
#[error("Unexpected FalkorDB response shape: {0}")]
MalformedResponse(String),
#[error(
"DoPut command unrecognised: '{0}' (expected VERTICES:<label> or EDGES:<src>:<type>:<dst>)"
)]
UnknownPutCommand(String),
#[error("Column count mismatch: schema has {schema} columns but row has {row}")]
ColumnCountMismatch { schema: usize, row: usize },
/// A `--compact` reply referenced a label / property-key / relationship-type
/// ordinal this client has not cached. The query door catches exactly this,
/// refreshes the id→name catalogs (`CALL db.propertyKeys()` / `db.labels()`
/// / `db.relationshipTypes()`) and retries the decode once; reaching a
/// caller means the server answered with an id its own catalog cannot name.
#[error("compact reply names {kind} id {id}, but only {have} are cached — catalog refresh required")]
CompactIdUnknown {
kind: &'static str,
id: i64,
have: usize,
},
#[error("Transport error: {0}")]
Transport(#[from] tonic::transport::Error),
}
impl From<FlightSqlError> for tonic::Status {
fn from(e: FlightSqlError) -> Self {
match &e {
FlightSqlError::UnregisteredSchema(_) => tonic::Status::not_found(e.to_string()),
FlightSqlError::UnknownPutCommand(_) => tonic::Status::invalid_argument(e.to_string()),
_ => tonic::Status::internal(e.to_string()),
}
}
}