astrid-runtime/astrid · warning

No-CoW workspace does not support promote

Error message

No-CoW workspace does not support promote

What it means

The No-CoW workspace strategy writes directly to the workspace with no staging area, so there is nothing to commit. promote on this backend deliberately returns an Unsupported error rather than silently succeeding, because callers expecting copy-on-write semantics would otherwise believe staged changes were committed atomically.

Solutions

  1. Check whether the workspace actually uses CoW before calling promote (inspect the backend/strategy)
  2. If CoW is required, enable it in configuration and ensure the volume supports clonefile (APFS)
  3. If No-CoW is intended, remove or skip promote/rollback calls — writes are already committed
  4. Handle io::ErrorKind::Unsupported as a no-op-with-acknowledgement in generic workspace code

Example fix

// before
workspace.promote()?;
// after
if workspace.supports_cow() {
    workspace.promote()?;
} // No-CoW: writes already went direct to the workspace
Defensive patterns

Strategy: type-guard

Validate before calling

fn promote_if_cow(ws: &dyn WorkspaceBackend) -> io::Result<()> {
    if ws.strategy() == Strategy::NoCow {
        return Ok(()); // writes already committed direct
    }
    ws.promote()
}

Type guard

fn supports_cow(ws: &dyn WorkspaceBackend) -> bool {
    ws.strategy() != Strategy::NoCow
}

Try / catch

match ws.promote() {
    Err(e) if e.kind() == io::ErrorKind::Unsupported => {
        tracing::debug!("No-CoW workspace: nothing to promote");
        Ok(())
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling promote() on a WorkspaceBackend constructed in No-CoW mode (e.g., APFS clone unavailable, non-supporting filesystem, or CoW disabled in configuration).

Common situations: Running on a filesystem/platform without clonefile support (non-APFS macOS volume, Linux); CoW explicitly disabled via config; code written against the CoW API deployed to an environment that fell back to No-CoW.

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/efaed8529598773e. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-vfs/src/workspace_cow/mod.rs:152

impl WorkspaceCow for NoCow {
    fn capability(&self) -> CowCapability {
        CowCapability::None
    }

    fn prepare(&self, pristine: &Path) -> io::Result<PreparedWorkspace> {
        Ok(PreparedWorkspace {
            merged_path: pristine.to_path_buf(),
            mask_from_children: Vec::new(),
        })
    }

    fn promote(&self) -> io::Result<()> {
        tracing::warn!(
            "workspace CoW: promote requested on a No-CoW workspace — writes already \
             went direct to the workspace, there is nothing to commit"
        );
        Err(io::Error::new(
            io::ErrorKind::Unsupported,
            "No-CoW workspace does not support promote",
        ))
    }

    fn rollback(&self) -> io::Result<()> {
        tracing::warn!(
            "workspace CoW: rollback requested on a No-CoW workspace — writes already \
             went direct to the workspace and cannot be rolled back"
        );
        Err(io::Error::new(
            io::ErrorKind::Unsupported,
            "No-CoW workspace does not support rollback",
        ))
    }

    fn teardown(&self) {}
}

View on GitHub (pinned to affd8760f4)