Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Error Types

AnyFS defines a unified error type for all filesystem operations.

FsError

The core error type used by all traits:

#![allow(unused)]
fn main() {
use anyfs_backend::FsError;
use std::path::Path;

fn handle_error(e: FsError) {
    match e {
        FsError::NotFound { path, operation } => {
            println!("{} not found during {}", path.display(), operation);
        }
        FsError::AlreadyExists { path, operation } => {
            println!("{} already exists during {}", path.display(), operation);
        }
        FsError::PermissionDenied { path, operation } => {
            println!("Permission denied: {} during {}", path.display(), operation);
        }
        FsError::Io { source, path, operation } => {
            println!("IO error on {}: {} during {}", 
                path.map(|p| p.display().to_string()).unwrap_or_default(),
                source, operation);
        }
        // ... handle other variants
    }
}
}

Error Variants

VariantWhen UsedRequired Fields
NotFoundFile or directory doesn’t existpath, operation
AlreadyExistsCreating something that existspath, operation
PermissionDeniedAccess not allowedpath, operation
IsDirectoryExpected file, got directorypath, operation
NotDirectoryExpected directory, got filepath, operation
DirectoryNotEmptyRemoving non-empty directorypath, operation
InvalidPathMalformed pathpath, operation, reason
TooManySymlinksSymlink loop detectedpath, operation
ReadOnlyWrite on read-only filesystempath, operation
CrossDeviceCross-filesystem operationsource, destination, operation
IoGeneral I/O errorsource, path (optional), operation
OtherUnclassified errorsmessage, operation

Creating Errors

Use the constructor methods for clean error creation:

#![allow(unused)]
fn main() {
use anyfs_backend::FsError;
use std::path::Path;

// NotFound
let err = FsError::not_found(Path::new("/missing.txt"), "read");

// AlreadyExists
let err = FsError::already_exists(Path::new("/exists"), "create_dir");

// PermissionDenied
let err = FsError::permission_denied(Path::new("/secret"), "read");

// IsDirectory
let err = FsError::is_directory(Path::new("/folder"), "read");

// NotDirectory
let err = FsError::not_directory(Path::new("/file.txt"), "read_dir");

// DirectoryNotEmpty
let err = FsError::directory_not_empty(Path::new("/folder"), "remove_dir");

// InvalidPath
let err = FsError::invalid_path(
    Path::new("/bad\0path"),
    "contains null byte",
    "open"
);

// ReadOnly
let err = FsError::read_only(Path::new("/file.txt"), "write");

// IO error
let err = FsError::io(
    std::io::Error::new(std::io::ErrorKind::Other, "disk full"),
    Some(Path::new("/file.txt")),
    "write"
);
}

Error Conversion

From std::io::Error

#![allow(unused)]
fn main() {
use anyfs_backend::FsError;
use std::io;

fn from_io_error(e: io::Error, path: &Path, op: &str) -> FsError {
    FsError::io(e, Some(path), op)
}

// Or use From trait (without path context)
let io_err = io::Error::new(io::ErrorKind::NotFound, "not found");
let fs_err: FsError = io_err.into();
}

To std::io::Error

#![allow(unused)]
fn main() {
use anyfs_backend::FsError;
use std::io;

let fs_err = FsError::not_found(Path::new("/missing"), "read");
let io_err: io::Error = fs_err.into();

assert_eq!(io_err.kind(), io::ErrorKind::NotFound);
}

Error Display

All errors implement Display with helpful messages:

#![allow(unused)]
fn main() {
let err = FsError::not_found(Path::new("/file.txt"), "read");
println!("{}", err);
// Output: not found: /file.txt (during read)

let err = FsError::permission_denied(Path::new("/secret"), "open");
println!("{}", err);
// Output: permission denied: /secret (during open)
}

Best Practices

1. Always Include Operation Context

#![allow(unused)]
fn main() {
// ✓ Good - includes operation
FsError::not_found(path, "read")

// ✗ Bad - no context
FsError::NotFound { path: path.into(), operation: String::new() }
}

2. Include Path When Available

#![allow(unused)]
fn main() {
// ✓ Good - includes path
FsError::io(e, Some(path), "write")

// ✗ Avoid - loses context
FsError::io(e, None, "write")
}

3. Use Specific Error Types

#![allow(unused)]
fn main() {
// ✓ Good - specific error
if path.exists() {
    return Err(FsError::already_exists(path, "create"));
}

// ✗ Avoid - generic error
return Err(FsError::other("file exists", "create"));
}

4. Pattern Match for Handling

#![allow(unused)]
fn main() {
match fs.read(path) {
    Ok(data) => process(data),
    Err(FsError::NotFound { .. }) => create_default(),
    Err(FsError::PermissionDenied { .. }) => request_access(),
    Err(e) => return Err(e),
}
}