pub trait SzErrorInspect {
// Required method
fn sz_error(&self) -> Option<&SzError>;
// Provided methods
fn is_sz_retryable(&self) -> bool { ... }
fn is_sz_unrecoverable(&self) -> bool { ... }
fn is_sz_bad_input(&self) -> bool { ... }
fn is_sz(&self, category: ErrorCategory) -> bool { ... }
}Expand description
Inspect any error chain for an embedded SzError.
Automatically implemented for every type that implements
std::error::Error + 'static, including Box<dyn Error>,
anyhow::Error, and custom error enums. The methods walk the
source() chain, find the first
SzError (if any), and expose its classification — no manual
downcasting required.
§Examples
§Senzing-only functions
When every call returns SzResult, you can use the native methods
directly. SzErrorInspect also works here (it finds the SzError
immediately since there is no wrapping), but the native methods
are equivalent:
use sz_rust_sdk::prelude::*;
use std::thread;
use std::time::Duration;
fn add_with_retry(
engine: &dyn SzEngine,
record_json: &str,
max_retries: u32,
) -> SzResult<String> {
let mut attempt = 0;
loop {
match engine.add_record("CUSTOMERS", "1", record_json, None) {
Ok(info) => return Ok(info),
Err(ref e) if e.is_retryable() && attempt < max_retries => {
attempt += 1;
let delay = Duration::from_millis(100 * 2u64.pow(attempt));
eprintln!("Retryable (attempt {attempt}/{max_retries}): {e}");
thread::sleep(delay);
}
Err(e) => return Err(e),
}
}
}§Functions that mix Senzing with other error types
When a function calls both Senzing and non-Senzing operations, Rust’s
? operator needs a single error type for the return. The standard
approach is Result<T, Box<dyn Error>> (or anyhow::Result<T>, or a
custom enum — whatever the application already uses). SzErrorInspect
works on all of them:
use sz_rust_sdk::prelude::*;
use std::fs;
/// Load records from a JSON file into the Senzing repository.
fn load_from_file(
engine: &dyn SzEngine,
path: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let data = fs::read_to_string(path)?; // io::Error on failure
let records: Vec<serde_json::Value> =
serde_json::from_str(&data)?; // serde::Error on failure
for record in &records {
let id = record["RECORD_ID"].as_str().unwrap_or("unknown");
let json = serde_json::to_string(record)?; // serde::Error
engine.add_record("CUSTOMERS", id, &json, None)?; // SzError
}
Ok(())
}
// At the call site, SzErrorInspect methods work on any error in the chain.
// They return false for io::Error, serde::Error, or anything that isn't
// a Senzing error.
match load_from_file(&*engine, "records.json") {
Ok(()) => println!("All records loaded"),
Err(ref e) if e.is_sz_retryable() => {
eprintln!("Transient Senzing error, retry: {e}");
}
Err(ref e) if e.is_sz(ErrorCategory::NotFound) => {
eprintln!("Entity not found: {e}");
}
Err(ref e) if e.is_sz_unrecoverable() => {
eprintln!("Unrecoverable Senzing error: {e}");
}
Err(e) => eprintln!("Error: {e}"),
}§Extracting the SzError for detailed inspection
Use sz_error() to get the underlying
SzError reference, then inspect its error code, message, severity,
or full category hierarchy:
use sz_rust_sdk::prelude::*;
fn handle_error(err: &(dyn std::error::Error + 'static)) {
match err.sz_error() {
Some(sz) => {
eprintln!("Senzing error [{}]: {}", sz.category(), sz.message());
eprintln!(" Severity: {}", sz.severity());
if let Some(code) = sz.error_code() {
eprintln!(" Native code: {code}");
}
}
None => eprintln!("Non-Senzing error: {err}"),
}
}§Granular classification with is_sz(ErrorCategory)
is_sz() checks the full hierarchy — a
DatabaseTransient error matches both ErrorCategory::DatabaseTransient
and its parent ErrorCategory::Retryable. Check specific types first,
then broader categories:
use sz_rust_sdk::prelude::*;
fn classify(err: &(dyn std::error::Error + 'static)) -> &'static str {
if err.is_sz(ErrorCategory::DatabaseConnectionLost) {
"database connection lost — check connectivity"
} else if err.is_sz(ErrorCategory::DatabaseTransient) {
"transient database issue — retry immediately"
} else if err.is_sz(ErrorCategory::Retryable) {
"retryable — retry with backoff"
} else if err.is_sz(ErrorCategory::NotFound) {
"entity not found — check record ID"
} else if err.is_sz(ErrorCategory::BadInput) {
"invalid input — fix request data"
} else if err.is_sz(ErrorCategory::License) {
"license error — check Senzing license"
} else if err.is_sz(ErrorCategory::Unrecoverable) {
"unrecoverable — reinitialize the SDK"
} else {
"non-Senzing error"
}
}§Custom error enum
Any error type that implements std::error::Error and returns the
inner SzError from source() works automatically:
use sz_rust_sdk::prelude::*;
#[derive(Debug)]
enum AppError {
Senzing(SzError),
Io(std::io::Error),
}
impl std::fmt::Display for AppError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Senzing(e) => write!(f, "senzing: {e}"),
Self::Io(e) => write!(f, "io: {e}"),
}
}
}
impl std::error::Error for AppError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Senzing(e) => Some(e),
Self::Io(e) => Some(e),
}
}
}
let err = AppError::Senzing(SzError::database_transient("Deadlock"));
assert!(err.is_sz_retryable());
assert!(err.is_sz(ErrorCategory::DatabaseTransient));
let err = AppError::Io(std::io::Error::new(
std::io::ErrorKind::NotFound, "file missing"
));
assert!(!err.is_sz_retryable());
assert!(err.sz_error().is_none());Required Methods§
Sourcefn sz_error(&self) -> Option<&SzError>
fn sz_error(&self) -> Option<&SzError>
Returns a reference to the first SzError found in the error chain,
or None if no SzError is present.
This is the foundation method that all other SzErrorInspect methods
build upon. Use it when you need direct access to the SzError for
detailed inspection (error code, message, component, hierarchy).
§Examples
use sz_rust_sdk::prelude::*;
let err = SzError::license("License expired");
let boxed: Box<dyn std::error::Error + Send + Sync> = Box::new(err);
// Extract the SzError from the Box
let sz = boxed.sz_error().expect("should contain an SzError");
assert!(sz.is_license());
assert_eq!(sz.severity(), "critical");Provided Methods§
Sourcefn is_sz_retryable(&self) -> bool
fn is_sz_retryable(&self) -> bool
Returns true if the chain contains a retryable SzError.
Retryable errors are temporary failures where the same operation may succeed if attempted again. This includes:
SzError::Retryable— generic retryable errorSzError::DatabaseConnectionLost— database connection droppedSzError::DatabaseTransient— deadlocks, lock timeouts, etc.SzError::RetryTimeoutExceeded— retry budget exhausted
Returns false if no SzError exists in the chain, or if the
SzError is not retryable.
§Examples
use sz_rust_sdk::prelude::*;
// Retryable Senzing error
let err = SzError::database_transient("Deadlock");
assert!(err.is_sz_retryable());
// Non-retryable Senzing error
let err = SzError::not_found("Entity 42");
assert!(!err.is_sz_retryable());
// Non-Senzing error
let err = std::io::Error::new(std::io::ErrorKind::BrokenPipe, "pipe broke");
assert!(!err.is_sz_retryable());Sourcefn is_sz_unrecoverable(&self) -> bool
fn is_sz_unrecoverable(&self) -> bool
Returns true if the chain contains an unrecoverable SzError.
Unrecoverable errors indicate the SDK is in a broken state and typically requires reinitialization. This includes:
SzError::Unrecoverable— generic unrecoverable errorSzError::Database— permanent database failure (schema errors, corruption)SzError::License— license expired or invalidSzError::NotInitialized— SDK not initializedSzError::Unhandled— unexpected internal error
Returns false if no SzError exists in the chain, or if the
SzError is not unrecoverable.
§Examples
use sz_rust_sdk::prelude::*;
let err = SzError::license("License expired");
assert!(err.is_sz_unrecoverable());
let err = SzError::database_transient("Deadlock");
assert!(!err.is_sz_unrecoverable()); // retryable, not unrecoverableSourcefn is_sz_bad_input(&self) -> bool
fn is_sz_bad_input(&self) -> bool
Returns true if the chain contains a bad-input SzError.
Bad input errors indicate the caller provided invalid data. This includes:
SzError::BadInput— generic invalid inputSzError::NotFound— entity or record not foundSzError::UnknownDataSource— unregistered data source name
Returns false if no SzError exists in the chain, or if the
SzError is not a bad-input error.
§Examples
use sz_rust_sdk::prelude::*;
let err = SzError::unknown_data_source("FAKE_SOURCE");
assert!(err.is_sz_bad_input());
let err = SzError::configuration("Bad config");
assert!(!err.is_sz_bad_input()); // configuration, not bad inputSourcefn is_sz(&self, category: ErrorCategory) -> bool
fn is_sz(&self, category: ErrorCategory) -> bool
Returns true if the chain contains an SzError matching the
given ErrorCategory.
This is the most flexible inspection method. It delegates to
SzError::is(), which checks the full error hierarchy. A
DatabaseTransient error matches both ErrorCategory::DatabaseTransient
(its specific type) and ErrorCategory::Retryable (its parent category).
Returns false if no SzError exists in the chain, or if the
SzError does not match the category.
§Available categories
| Category | Parent | Matches |
|---|---|---|
BadInput | — | BadInput, NotFound, UnknownDataSource |
NotFound | BadInput | NotFound only |
UnknownDataSource | BadInput | UnknownDataSource only |
Retryable | — | Retryable, DatabaseConnectionLost, DatabaseTransient, RetryTimeoutExceeded |
DatabaseConnectionLost | Retryable | DatabaseConnectionLost only |
DatabaseTransient | Retryable | DatabaseTransient only |
RetryTimeoutExceeded | Retryable | RetryTimeoutExceeded only |
Unrecoverable | — | Unrecoverable, Database, License, NotInitialized, Unhandled |
Database | Unrecoverable | Database only |
License | Unrecoverable | License only |
NotInitialized | Unrecoverable | NotInitialized only |
Unhandled | Unrecoverable | Unhandled only |
Configuration | — | Configuration only |
ReplaceConflict | — | ReplaceConflict only |
EnvironmentDestroyed | — | EnvironmentDestroyed only |
Unknown | — | Unknown only |
§Examples
use sz_rust_sdk::prelude::*;
let err = SzError::database_transient("Deadlock");
// Exact match
assert!(err.is_sz(ErrorCategory::DatabaseTransient));
// Parent category match
assert!(err.is_sz(ErrorCategory::Retryable));
// Not in this hierarchy
assert!(!err.is_sz(ErrorCategory::BadInput));
assert!(!err.is_sz(ErrorCategory::Unrecoverable));