SzErrorInspect

Trait SzErrorInspect 

Source
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§

Source

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§

Source

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:

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());
Source

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:

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 unrecoverable
Source

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:

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 input
Source

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
CategoryParentMatches
BadInputBadInput, NotFound, UnknownDataSource
NotFoundBadInputNotFound only
UnknownDataSourceBadInputUnknownDataSource only
RetryableRetryable, DatabaseConnectionLost, DatabaseTransient, RetryTimeoutExceeded
DatabaseConnectionLostRetryableDatabaseConnectionLost only
DatabaseTransientRetryableDatabaseTransient only
RetryTimeoutExceededRetryableRetryTimeoutExceeded only
UnrecoverableUnrecoverable, Database, License, NotInitialized, Unhandled
DatabaseUnrecoverableDatabase only
LicenseUnrecoverableLicense only
NotInitializedUnrecoverableNotInitialized only
UnhandledUnrecoverableUnhandled only
ConfigurationConfiguration only
ReplaceConflictReplaceConflict only
EnvironmentDestroyedEnvironmentDestroyed only
UnknownUnknown 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));

Implementations on Foreign Types§

Source§

impl SzErrorInspect for dyn Error + 'static

Source§

impl SzErrorInspect for dyn Error + Send + 'static

Source§

impl SzErrorInspect for dyn Error + Send + Sync + 'static

Implementors§

Source§

impl<E: Error + 'static> SzErrorInspect for E