{"record":{"id":"efaed8529598773e","repo":"astrid-runtime/astrid","slug":"no-cow-workspace-does-not-support-promote","errorCode":null,"errorMessage":"No-CoW workspace does not support promote","messagePattern":"No-CoW workspace does not support promote","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/astrid-vfs/src/workspace_cow/mod.rs","lineNumber":152,"sourceCode":"\nimpl WorkspaceCow for NoCow {\n    fn capability(&self) -> CowCapability {\n        CowCapability::None\n    }\n\n    fn prepare(&self, pristine: &Path) -> io::Result<PreparedWorkspace> {\n        Ok(PreparedWorkspace {\n            merged_path: pristine.to_path_buf(),\n            mask_from_children: Vec::new(),\n        })\n    }\n\n    fn promote(&self) -> io::Result<()> {\n        tracing::warn!(\n            \"workspace CoW: promote requested on a No-CoW workspace — writes already \\\n             went direct to the workspace, there is nothing to commit\"\n        );\n        Err(io::Error::new(\n            io::ErrorKind::Unsupported,\n            \"No-CoW workspace does not support promote\",\n        ))\n    }\n\n    fn rollback(&self) -> io::Result<()> {\n        tracing::warn!(\n            \"workspace CoW: rollback requested on a No-CoW workspace — writes already \\\n             went direct to the workspace and cannot be rolled back\"\n        );\n        Err(io::Error::new(\n            io::ErrorKind::Unsupported,\n            \"No-CoW workspace does not support rollback\",\n        ))\n    }\n\n    fn teardown(&self) {}\n}","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-vfs/src/workspace_cow/mod.rs#L134-L170","documentation":"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.","triggerScenarios":"Calling promote() on a WorkspaceBackend constructed in No-CoW mode (e.g., APFS clone unavailable, non-supporting filesystem, or CoW disabled in configuration).","commonSituations":"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.","solutions":["Check whether the workspace actually uses CoW before calling promote (inspect the backend/strategy)","If CoW is required, enable it in configuration and ensure the volume supports clonefile (APFS)","If No-CoW is intended, remove or skip promote/rollback calls — writes are already committed","Handle io::ErrorKind::Unsupported as a no-op-with-acknowledgement in generic workspace code"],"exampleFix":"// before\nworkspace.promote()?;\n// after\nif workspace.supports_cow() {\n    workspace.promote()?;\n} // No-CoW: writes already went direct to the workspace","handlingStrategy":"type-guard","validationCode":"fn promote_if_cow(ws: &dyn WorkspaceBackend) -> io::Result<()> {\n    if ws.strategy() == Strategy::NoCow {\n        return Ok(()); // writes already committed direct\n    }\n    ws.promote()\n}","typeGuard":"fn supports_cow(ws: &dyn WorkspaceBackend) -> bool {\n    ws.strategy() != Strategy::NoCow\n}","tryCatchPattern":"match ws.promote() {\n    Err(e) if e.kind() == io::ErrorKind::Unsupported => {\n        tracing::debug!(\"No-CoW workspace: nothing to promote\");\n        Ok(())\n    }\n    other => other,\n}","preventionTips":["Query the workspace strategy/CoW capability before calling promote","Make promote/rollback calls conditional on CoW mode in generic code","If CoW semantics are required, verify APFS availability at startup and fail fast otherwise","Document in the commit path that No-CoW writes are already durable"],"tags":["cow","workspace","unsupported"],"backgroundTag":"unsupported-operation","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}