{"record":{"id":"b8dc5e5a9aa449ce","repo":"astrid-runtime/astrid","slug":"context","errorCode":null,"errorMessage":"{context}","messagePattern":"\\{context\\}","errorType":"error_code","errorClass":"ContextualIoError","httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/platform_fs/windows/error.rs","lineNumber":28,"sourceCode":"struct ContextualIoError {\n    context: String,\n    source: io::Error,\n}\n\nimpl fmt::Display for ContextualIoError {\n    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(formatter, \"{}: {}\", self.context, self.source)\n    }\n}\n\nimpl std::error::Error for ContextualIoError {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        Some(&self.source)\n    }\n}\n\npub(super) fn with_context(error: io::Error, context: impl Into<String>) -> io::Error {\n    io::Error::new(\n        error.kind(),\n        ContextualIoError {\n            context: context.into(),\n            source: error,\n        },\n    )\n}\n\n#[cfg(test)]\npub(super) fn native_error_code(error: &io::Error) -> Option<i32> {\n    if let Some(code) = error.raw_os_error() {\n        return Some(code);\n    }\n    let mut source = error.source();\n    while let Some(current) = source {\n        if let Some(error) = current.downcast_ref::<io::Error>()\n            && let Some(code) = error.raw_os_error()\n        {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/platform_fs/windows/error.rs#L10-L46","documentation":"with_context is the library's generic error-wrapper: it re-packages an underlying io::Error into a new io::Error of the same ErrorKind whose Display message is the supplied context string and whose source() chain preserves the original error. Hitting this means an OS operation failed and the library added human-readable context about which guarded file operation failed. Inspect the error's source() chain for the root cause (e.g. sharing violation, access denied, path not found).","triggerScenarios":"Any of the wrapped call sites fails: acquire_named_private_lock (lock contention/permissions), replace_file_checked, move_guarded_file, remove_guarded_file (rename/remove races or denied access) inside the guarded-file layer.","commonSituations":"File locked by another process or an antivirus scanner during replace/move; insufficient privileges to rename or delete inside a trusted directory; target path in use (ERROR_SHARING_VIOLATION); leftover handles from a crashed process holding the lock.","solutions":["Inspect err.source() (walk the chain) to find the original io::Error kind and OS error code","Retry the operation if the source kind was transient (sharing violation / lock temporarily held)","Close other handles to the file (other processes, editors, AV scans) before retrying","Run with sufficient privileges for operations inside the trusted directory"],"exampleFix":"// before: matching only on the wrapped message\nif err.to_string().contains(\"replace\") { ... }\n// after: unwrap the context to branch on the root cause\nlet mut src: Option<&(dyn std::error::Error + 'static)> = err.source();\nwhile let Some(e) = src { eprintln!(\"caused by: {e}\"); src = e.source(); }\nif err.kind() == io::ErrorKind::PermissionDenied { /* escalate or fix ACL */ }","handlingStrategy":"try-catch","validationCode":"// Pre-flight the guarded operation's target: existence and writability\nfn can_modify(path: &std::path::Path) -> bool {\n    match std::fs::OpenOptions::new().write(true).open(path) {\n        Ok(_) => true,\n        Err(_) => false,\n    }\n}","typeGuard":null,"tryCatchPattern":"match guarded_op() {\n    Err(e) if e.kind() == io::ErrorKind::PermissionDenied || e.kind() == io::ErrorKind::AlreadyExists => {\n        // walk e.source() for the native error code, then retry or escalate\n    }\n    other => other?,\n}","preventionTips":["Always walk error.source() to see the native OS error behind the context wrapper","Close competing handles (AV scanners, other processes) before file replace/move/delete","Retry once on sharing violations before surfacing the error","Run with privileges appropriate for the trusted directory"],"tags":["windows","fs","io","error-wrapping"],"backgroundTag":"invalid-state-transition","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}