astrid-runtime/astrid · warning · io::Error
volume backend does not provide physical reclamation
Error message
volume backend does not provide physical reclamation
What it means
The default Volume trait reclaim() implementation returns io::ErrorKind::Unsupported because the backend has no safe physical reclamation primitive (e.g. TRIM/deallocate). Only backends that explicitly override reclaim() can physically free space; calling it on a default backend always fails.
Solutions
- Check backend capability before calling and skip reclaim gracefully when Unsupported is returned
- Match on err.kind() == io::ErrorKind::Unsupported and treat as a no-op
- Use a backend that overrides reclaim() with a real primitive
- Document/log that reclamation is unavailable for this backend instead of failing the maintenance job
Example fix
// before
volume.reclaim()?;
// after
if let Err(e) = volume.reclaim() {
if e.kind() != std::io::ErrorKind::Unsupported { return Err(e); } // skip: backend can't reclaim
} Defensive patterns
Strategy: fallback
Validate before calling
// No pre-check API; guard by kind after the call:
fn reclaim_if_supported(v: &dyn Volume) -> io::Result<bool> {
match v.reclaim() { Ok(()) => Ok(true), Err(e) if e.kind() == io::ErrorKind::Unsupported => Ok(false), Err(e) => Err(e) }
} Type guard
fn supports_reclaim(v: &dyn Volume) -> bool { v.reclaim().map(|_| true).or_else(|e| if e.kind() == io::ErrorKind::Unsupported { Ok(false) } else { Err(e) }).unwrap_or(true) } Try / catch
match volume.reclaim() {
Err(e) if e.kind() == std::io::ErrorKind::Unsupported => log::info!("backend cannot reclaim; skipping"),
other => other?,
} Prevention
- Treat Unsupported as a capability signal, not a failure
- Wrap reclaim in a helper that returns Option/bool
- Document per-backend reclaim support in your infra code
- Only call reclaim in maintenance jobs where skipping is safe
When it happens
Trigger: Calling volume.reclaim() on a backend that does not override the trait default, e.g. HostedFileVolume or any custom backend implementing only the required methods.
Common situations: Building a space-reclamation/maintenance routine that assumes all backends support TRIM-like operations; portable code calling reclaim() without checking backend capability.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- audit read failed
- destination.as_str()
- invalid Astrid volume record length at
- invalid interior Astrid volume record length at
- non-UTF-8 region name
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/e957f8103187d3d1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-storage/src/volume.rs:234
/// Returns an underlying media-capacity error.
fn available_space(&self) -> io::Result<Option<u64>> {
Ok(None)
}
/// Physically reclaim obsolete container extents after a logical rewrite.
///
/// The operation is invoked only after the replacement namespace and its
/// evidence are durable. Implementations must use their own crash-safe
/// media transaction; the default rejects backends that cannot provide a
/// reclaim boundary, so callers never mistake logical reachability for
/// physical reclamation.
///
/// # Errors
///
/// Returns [`io::ErrorKind::Unsupported`] when the backend has no safe
/// reclaim primitive, or an underlying media error.
fn reclaim(&self) -> io::Result<()> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"volume backend does not provide physical reclamation",
))
}
/// Flush all preceding volume mutations to durable media.
///
/// # Errors
///
/// Returns an underlying durability-barrier error.
fn sync(&self) -> io::Result<()>;
}
/// Seekable handle to one region in an [`AstridVolume`].
#[derive(Clone)]
pub struct VolumeFile {
volume: Arc<dyn AstridVolume>,
region: VolumeRegion,View on GitHub (pinned to affd8760f4)