Skip to main content

Error Types Reference

vpt-rs uses a single Error enum for all failure modes. A convenience alias Result<T> wraps std::result::Result<T, Error>. The enum derives thiserror::Error, so every variant implements Display and std::error::Error automatically.

use vpt_rs::{Error, Result};

The Error Enum​

UnsupportedOperation​

The backend does not implement the requested operation.

use vpt_rs::Error;

let err = Error::UnsupportedOperation {
operation: "backup_volume",
backend: "linux-stub",
};
println!("{err}");
// "operation `backup_volume` is not supported by backend `linux-stub`"
FieldTypeDescription
operation&'static strName of the failed operation
backend&'static strBackend that does not support it

MissingCapability​

The backend exists but lacks a specific capability.

use vpt_rs::{Error, Capability};

let err = Error::MissingCapability {
capability: Capability::ApplicationConsistentSnapshot.as_str(),
backend: "linux-btrfs",
};
println!("{err}");
// "capability `application_consistent_snapshot` is not available on backend `linux-btrfs`"
FieldTypeDescription
capability&'static strThe missing capability name
backend&'static strBackend that lacks it

InvalidVolume​

A volume reference is empty or malformed.

use vpt_rs::Error;

let err = Error::InvalidVolume {
volume: String::new(),
};
println!("{err}");
// "invalid volume reference ``"
FieldTypeDescription
volumeStringThe problematic volume identifier

MissingPath​

An expected filesystem path does not exist.

use vpt_rs::Error;
use std::path::PathBuf;

let err = Error::MissingPath {
path: PathBuf::from("/tmp/nonexistent.img"),
};
println!("{err}");
// "path does not exist: /tmp/nonexistent.img"
FieldTypeDescription
pathPathBufThe missing filesystem path

Io​

Wraps a standard I/O error. The From<std::io::Error> implementation is provided, so the ? operator converts automatically.

use vpt_rs::Error;

let io_err = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
let err: Error = io_err.into();
println!("{err}");
// "io error: access denied"
tip

Because Error implements From<std::io::Error>, you can use ? on any std::io operation inside a function returning Result<T>.

InvalidArgument​

A function argument is semantically invalid.

use vpt_rs::Error;

let err = Error::InvalidArgument {
message: "block_size must be a power of 2".to_string(),
};
println!("{err}");
// "invalid argument: block_size must be a power of 2"
FieldTypeDescription
messageStringHuman-readable explanation of the problem

CommandFailed​

An external command exited with a non-zero status. This is the most common error when backends shell out to tools like btrfs, zfs, or dd.

use vpt_rs::Error;

let err = Error::CommandFailed {
command: "btrfs subvolume snapshot -r /mnt/data /mnt/data/snap".to_string(),
status: 1,
stderr: "ERROR: cannot snapshot /mnt/data: not a btrfs filesystem".to_string(),
};
println!("{err}");
// "command `btrfs subvolume snapshot ...` failed with status 1: ERROR: cannot snapshot ..."
FieldTypeDescription
commandStringThe command that was executed
statusi32Exit code
stderrStringCaptured standard error output

Timeout​

An external command exceeded the configured timeout (default 30 seconds, configurable via VPT_COMMAND_TIMEOUT_SECS).

use vpt_rs::Error;

let err = Error::Timeout {
operation: "backup_volume",
backend: "linux-zfs",
timeout_secs: 30,
};
println!("{err}");
// "operation `backup_volume` on backend `linux-zfs` timed out after 30s"
FieldTypeDescription
operation&'static strThe operation that timed out
backend&'static strBackend that was running it
timeout_secsu64The timeout value in seconds

Message​

A catch-all variant for errors that do not fit the other categories.

use vpt_rs::Error;

let err = Error::Message {
message: "internal invariant violated: snapshot list returned None".to_string(),
};
println!("{err}");
// "internal invariant violated: snapshot list returned None"
FieldTypeDescription
messageStringThe error description

Result Type Alias​

pub type Result<T> = std::result::Result<T, Error>;

Use this in your own functions that call vpt-rs APIs:

use vpt_rs::{BackupPlan, Result};

fn create_plan() -> Result<BackupPlan> {
// ... build the plan
# todo!()
}

Accessors​

timeout_secs()​

Returns Some(u64) if the error is a Timeout variant, None otherwise.

use vpt_rs::Error;

let err = Error::Timeout {
operation: "restore_volume",
backend: "linux-lvm",
timeout_secs: 60,
};
assert_eq!(err.timeout_secs(), Some(60));

let err2 = Error::InvalidArgument {
message: "bad".to_string(),
};
assert_eq!(err2.timeout_secs(), None);

Matching on Specific Variants​

Use match or if let to handle individual error kinds.

use vpt_rs::Error;

fn describe_error(err: &Error) {
match err {
Error::Timeout { operation, timeout_secs, .. } => {
eprintln!("timed out after {timeout_secs}s during {operation}");
}
Error::CommandFailed { command, status, .. } => {
eprintln!("command `{command}` failed with exit code {status}");
}
Error::MissingPath { path } => {
eprintln!("file not found: {}", path.display());
}
other => {
eprintln!("unexpected error: {other}");
}
}
}

Error Handling Patterns​

Using the ? operator​

Because Error implements From<std::io::Error>, you can use ? on any I/O call inside a function returning Result<T>:

use std::fs;
use vpt_rs::{VolumeRef, Result, SnapshotRequest, SnapshotKind};

fn read_and_snapshot(path: &str) -> Result<()> {
let _contents = fs::read_to_string(path)?; // io::Error -> Error::Io
let request = SnapshotRequest {
source: VolumeRef::new(path),
kind: SnapshotKind::CrashConsistent,
label: None,
read_only: true,
};
// backend.create_snapshot(&request)?;
Ok(())
}

Mapping errors with context​

Use .map_err() to wrap errors with additional context:

use vpt_rs::{Error, Result};

fn load_config(path: &str) -> Result<String> {
std::fs::read_to_string(path).map_err(|e| {
Error::Message {
message: format!("failed to load config from `{path}`: {e}"),
}
})
}

Checking for timeout errors​

use vpt_rs::Error;

fn retry_on_timeout(err: &Error) -> bool {
err.timeout_secs().is_some()
}
caution

Do not pattern-match on the Display output strings. The string format is not part of the public API and may change. Always match on the enum variants.