{"record":{"id":"8a4a46d452784cb5","repo":"astrid-runtime/astrid","slug":"quarantine-to-error-8a4a46","errorCode":null,"errorMessage":"quarantine {} to {}: {error}","messagePattern":"quarantine (.+?) to (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/principal_home_migration/unbound.rs","lineNumber":241,"sourceCode":"            io::ErrorKind::InvalidData,\n            format!(\"principal {alias} has an invalid genesis public key: {error}\"),\n        )\n    })?;\n    Ok(public_key.into())\n}\n\nfn quarantine_entry(\n    home: &AstridHome,\n    source: &Path,\n    file_name: &OsStr,\n    reason: &str,\n) -> io::Result<()> {\n    let quarantine_root = home.migrations_dir().join(QUARANTINE_DIR);\n    astrid_core::platform_fs::ensure_private_directory(&quarantine_root)?;\n    let destination = unique_quarantine_path(&quarantine_root, file_name)?;\n    let source_parent = source.parent().map(Path::to_path_buf);\n    fs::rename(source, &destination).map_err(|error| {\n        io::Error::new(\n            error.kind(),\n            format!(\n                \"quarantine {} to {}: {error}\",\n                source.display(),\n                destination.display()\n            ),\n        )\n    })?;\n    if let Some(parent) = source_parent.as_deref() {\n        sync_directory(parent)?;\n    }\n    sync_parent(&destination)?;\n    let sidecar = destination.with_file_name(format!(\n        \"{}.original-name\",\n        destination\n            .file_name()\n            .map_or(\"leftover\", |name| name.to_str().unwrap_or(\"leftover\"))\n    ));","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/principal_home_migration/unbound.rs#L223-L259","documentation":"This error wraps a failed `fs::rename` while quarantining an unexpected file found in the principal home during migration. The kernel first moves the stray file into a private quarantine directory before continuing; if the OS rename fails, the original OS error kind is preserved and both source and destination paths are embedded in the message. It exists so migration never silently destroys or loses unexplained files.","triggerScenarios":"`quarantine_entry` (via `admit_or_quarantine_entry`) calls `fs::rename(source, destination)` and the OS rejects it: source file deleted/renamed concurrently, destination collision despite `unique_quarantine_path`, cross-device rename, or permission issues on the source or migrations dir.","commonSituations":"Another process (editor, sync tool like Dropbox/Nextcloud, backup agent) is touching files inside the home while migration runs; the home spans multiple filesystems so rename is EXDEV; the migrations directory was manually created with wrong permissions.","solutions":["Re-run the operation; transient locks from sync/backup tools usually clear once those tools are paused","Exclude the principal home directory from file sync/backup software","Check that the home and migrations directory are on the same filesystem and writable by the current user","Inspect the wrapped OS error kind in the message (e.g. EXDEV, EACCES, ENOENT) to target the filesystem/permission cause"],"exampleFix":"// before\nfs::rename(source, &destination)?;\n// after\n// fall back to copy+remove when rename fails across devices\nmatch fs::rename(source, &destination) {\n    Ok(()) => {},\n    Err(e) if e.kind() == io::ErrorKind::CrossesDevices => {\n        fs::copy(source, &destination)?;\n        fs::remove_file(source)?;\n    }\n    Err(e) => return Err(e),\n}","handlingStrategy":"try-catch","validationCode":"// before calling admission, ensure the home is quiescent and writable\nlet meta = std::fs::metadata(source)?;\nif !meta.is_file() { return Err(\"unexpected non-file entry\"); }\nlet test = std::fs::OpenOptions::new().append(true).open(source.parent().unwrap())?;","typeGuard":null,"tryCatchPattern":"match err.downcast_ref::<io::Error>() {\n    Some(e) if e.kind() == io::ErrorKind::CrossesDevices => /* copy+remove fallback */,\n    Some(e) if e.kind() == io::ErrorKind::PermissionDenied => /* fix perms, retry */,\n    _ => /* surface to user */,\n}","preventionTips":["Pause file-sync/backup tools that watch the principal home during migration","Keep the home on a single filesystem so rename never needs EXDEV fallback","Run migrations while no other app instance is open"],"tags":["filesystem","io","migration"],"backgroundTag":"file-write-failed","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"}