fs-err
A drop-in replacement for std::fs that adds file paths and operation context to every I/O error.
Repository Health
Technical Analysis
fs-err is a small Rust crate that wraps std::fs functions and types one-for-one, so switching to it is as simple as use fs_err as fs; with no other code changes required. Every wrapped call still returns a plain std::io::Error, but the Display message now includes the operation that failed and the exact path involved, instead of Rust’s default bare OS error string.
This makes it especially useful in CLIs, build tools, and long-running services where a raw “No such file or directory (os error 2)” gives no clue which of dozens of file operations actually failed. Optional features add async support via tokio, an opt-in mode that exposes the original io::Error as the error source for libraries like anyhow, and a debug feature that inspects the filesystem to explain why an operation failed (missing parent directory, permissions, etc.).
What You Get
- Drop-in module-level replacement for std::fs via
use fs_err as fs;— no call-site rewrites needed - Human-readable error messages that name the failed operation and the exact file path involved
- A
Filewrapper plus Unix/Windows extension traits (read_at, seek_read, chown, lock, etc.) with the same path-aware errors - Optional
tokiofeature providing async equivalents of the same wrapped API under fs_err::tokio - Optional
debugfeature that inspects the filesystem to explain why an operation failed (missing parent dir, permission issues) via the path_facts crate expose_original_errorfeature to surface the original io::Error asError::source()for libraries like anyhow that walk the error chain
Common Use Cases
- Wrapping filesystem access in CLI tools so users get an actionable error instead of a bare OS error code
- Debugging build scripts and code generators that read/write many files, where knowing which path failed saves time
- Improving error messages in long-running services without introducing a custom error type or changing existing error-handling code
- Adding path-aware async filesystem errors to tokio-based applications via the optional tokio feature
Under The Hood
Architecture
fs-err is architected as a thin wrapper layer around std::fs, split into small focused modules: lib.rs re-exports top-level free functions (read, write, copy, create_dir, rename, canonicalize, etc.) that mirror std::fs’s API one-to-one, dir.rs wraps ReadDir/DirEntry, file.rs wraps std::fs::File including platform-specific extension traits in nested unix/windows submodules for calls like read_at and seek_read, open_options.rs wraps OpenOptions, path.rs adds a sealed PathExt trait for extra path queries, and errors.rs centralizes an internal Error/SourceDestError type behind an ErrorKind enum that builds human-readable messages while still returning a plain io::Error, keeping the crate a true drop-in replacement. An optional tokio submodule mirrors the sync API asynchronously behind a feature flag, and a private Sealed trait in a private module prevents downstream crates from implementing PathExt, preserving forward compatibility for future additions.
Tech Stack
A Rust crate on edition 2018 with an MSRV of 1.40 and zero required dependencies. A build.rs script uses the autocfg build-dependency to detect the installed rustc version and emit cfg flags (rustc_1_63, rustc_1_75, rustc_1_79, rustc_1_81, rustc_1_89) that conditionally enable newer std::fs::File methods like set_times, exists, and file locking without raising the MSRV. Optional dependencies are tokio (feature “fs”) for async wrappers and path_facts (feature “debug”) for filesystem diagnostics; serde_json is a dev-dependency used only in doctest examples. CI on GitHub Actions builds and tests across Ubuntu and Windows on stable, beta, and the pinned MSRV toolchain, and separately runs cargo check against every individual feature combination to make sure each flag compiles in isolation.
Code Quality
No dedicated tests/ directory or #[cfg(test)] unit-test modules exist in the repository — verification relies on doctests embedded in the crate-level and per-function doc comments, exercised by cargo test, together with cargo clippy --tests -- -D warnings and cargo fmt --check gates that CI enforces on the stable toolchain leg. Error handling is explicit and consistent: every std::fs call is immediately mapped into a private Error or SourceDestError wrapped inside io::Error, never silently discarded, and a crate-level #![deny(missing_debug_implementations, missing_docs)] forces every public item to carry both documentation and a Debug impl. Naming deliberately mirrors std::fs (read, write, copy, rename, canonicalize) for zero-friction familiarity, and platform-specific code is isolated behind #[cfg(unix)]/#[cfg(windows)] with parallel trait implementations for each.
API Design
The crate’s core design decision is that it is a true drop-in: swapping use std::fs for use fs_err as fs; requires no other code changes, unlike most “better error” crates that require rewriting call sites around a new error type. Because fs-err deliberately keeps returning std::io::Error rather than introducing its own error enum, it composes for free with any code, trait (Read/Write/Seek), or library — such as anyhow or serde_json — that already expects a standard io::Error. The optional debug/debug_tokio features go further than most alternatives in this space by inspecting the filesystem at failure time to explain why an operation failed (missing parent directory, permission issues), a genuinely useful ergonomic addition that is opt-in specifically because it costs extra syscalls.
Used by 3 apps in this directory
Qdrant
Databases · AI Development · Search
Open-source vector database and search engine built in Rust for production-grade AI applications — from semantic search to RAG pipelines and recommendation systems.
QuestDB
Databases · Analytics
A high-performance, open-source time-series database built for financial market data, IoT telemetry, and real-time analytics, combining a zero-GC Java/C++ core with SIMD-accelerated SQL and a WAL-to-Parquet storage engine.
Svix
Developer Tools · Automation
Open source, self-hostable webhook infrastructure that handles delivery, retries, HMAC signing, and multi-tenant event management so you never have to build a webhooks system from scratch.