astrid-runtime/astrid · error
legacy log conflict at {}: {detail}
Error message
legacy log conflict at {}: {detail} What it means
The `conflict(path, detail)` helper raises an AlreadyExists error when something the migration wants to create or move to already exists in an unexpected way at the destination path. Unlike plain `invalid`, this is a collision problem, not malformed content. The message names the conflicting path and a specific detail.
Source
Thrown at crates/astrid-kernel/src/principal_log_migration.rs:554
fn sync_parent(path: &Path) -> io::Result<()> {
#[cfg(unix)]
if let Some(parent) = path.parent() {
File::open(parent)?.sync_all()?;
}
#[cfg(not(unix))]
let _ = path;
Ok(())
}
fn invalid(path: &Path, detail: &str) -> io::Error {
io::Error::new(
io::ErrorKind::InvalidData,
format!("legacy log {}: {detail}", path.display()),
)
}
fn conflict(path: &Path, detail: &str) -> io::Error {
io::Error::new(
io::ErrorKind::AlreadyExists,
format!("legacy log conflict at {}: {detail}", path.display()),
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn migrates_logs_to_uid_projection_and_is_idempotent() {
let temp = tempfile::tempdir().unwrap();
let home = AstridHome::from_path(temp.path().join("astrid"));
let principal = PrincipalId::new("alice").unwrap();
let uid = PrincipalUid::from_bytes([0x91; 32]);
let directory = PrincipalDirectory::default();
directory.register(principal.clone(), uid).unwrap();
let source = home.principal_home(&principal).log_dir();View on GitHub (pinned to affd8760f4)
Solutions
- Re-run the migration/idempotent admission pass — completed migrations are typically safe to resume and will reconcile leftovers
- Remove or archive the conflicting destination path if you know it is a stale leftover
- Ensure only one instance of the application performs migration at a time
- Check the `detail` in the message to see exactly which expected-fresh path collided
Defensive patterns
Strategy: retry
Validate before calling
// preflight yourself: ensure expected-fresh destinations don't exist
if destination_path.exists() {
archive_or_remove(&destination_path)?; // or abort and reconcile manually
} Try / catch
match res {
Err(e) if e.kind() == io::ErrorKind::AlreadyExists => retry_migration_after_reconciling(),
other => other,
} Prevention
- Run only one app instance during migration
- Complete interrupted migrations before starting new ones
- Don't restore backups on top of already-migrated homes without resetting
When it happens
Trigger: `migrate_one`, `preflight_destination`, `copy_entry`, `verify_entries`, `retire_source`, or `remove_empty_directories` find an existing file/directory where the migration expects none (destination entry already present, source reappeared after retirement, unexpected leftovers).
Common situations: A previous partially-completed migration left destination files behind; the user restored a backup on top of an already-migrated home; two instances of the app ran migrations concurrently.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- legacy and operator REPL histories differ; refusing to merge
- legacy audit retirement is ambiguous: {}
- legacy distro conflict at {path}: {detail}
- legacy capsule directory is not a regular directory: {}
- legacy capsule entry is not a regular directory: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/b7aad9760e2f1a1b.
Report an issue: GitHub.