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

  1. Check backend capability before calling and skip reclaim gracefully when Unsupported is returned
  2. Match on err.kind() == io::ErrorKind::Unsupported and treat as a no-op
  3. Use a backend that overrides reclaim() with a real primitive
  4. 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

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


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)