astrid-runtime/astrid · error
unsupported legacy audit source {}; only the default princip
Error message
unsupported legacy audit source {}; only the default principal source is admitted What it means
The legacy importer only admits the default principal's audit source. If preflight finds a non-default <principal>/.local/audit directory that is non-empty, it aborts with AlreadyExists, refusing to migrate or delete audit data belonging to a non-default principal. Empty non-default audit directories are tolerated and skipped.
Source
Thrown at crates/astrid-kernel/src/legacy_migration_barrier/host_fs.rs:430
Err(error) => return Err(error),
}
let audit_source = local_root.join("audit");
let audit_metadata = match fs::symlink_metadata(&audit_source) {
Ok(metadata) => metadata,
Err(error) if error.kind() == io::ErrorKind::NotFound => continue,
Err(error) => return Err(error),
};
if audit_source == default_source {
default_source_present = true;
validate_audit_tree(&audit_source, device_id(&audit_metadata))?;
} else if fs::read_dir(&audit_source)
.map_err(io::Error::other)?
.next()
.transpose()
.map_err(io::Error::other)?
.is_some()
{
return Err(io::Error::new(
io::ErrorKind::AlreadyExists,
format!(
"unsupported legacy audit source {}; only the default principal source is admitted",
audit_source.display()
),
));
}
}
Ok(default_source_present)
}
/// Retire the imported default audit tree through a private staging rename.
/// The rename makes interrupted deletion resumable, while every pre/post
/// traversal revalidates no-follow, regular-entry, device, and mount bounds.
#[cfg(not(unix))]
pub(super) fn retire_legacy_audit_dir(home: &AstridHome, source: &Path) -> io::Result<()> {
let retired = home.migrations_dir().join("audit-principal-home.retired");
let expected = home.principal_home(&PrincipalId::default()).audit_dir();View on GitHub (pinned to affd8760f4)
Solutions
- Archive or manually export the non-default principal's audit data, then empty or remove that audit directory and re-run.
- Confirm the extra audit tree is obsolete and delete it (it will not be migrated by design).
- If the data must be kept in-system, migrate it under the default principal id first, then run the legacy migration.
- Re-run migrate_legacy_audit once only the default principal's non-empty audit source remains.
Example fix
// before: second principal with audit data /home/u/principal-abc/.local/audit/ (3 files) // after $ tar czf principal-abc-audit.tgz -C /home/u/principal-abc/.local audit $ rm -r /home/u/principal-abc/.local/audit
Defensive patterns
Strategy: validation
Validate before calling
fn non_default_audit_sources(home_root: &std::path::Path, default_audit: &std::path::Path) -> std::io::Result<Vec<std::path::PathBuf>> {
let mut offenders = Vec::new();
for e in std::fs::read_dir(home_root)? {
let audit = e?.path().join(".local").join("audit");
if audit != default_audit
&& std::fs::symlink_metadata(&audit).map(|m| m.is_dir()).unwrap_or(false)
&& std::fs::read_dir(&audit)?.next().is_some()
{
offenders.push(audit);
}
}
Ok(offenders) // archive/delete these before migrating
} Try / catch
match result {
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists && e.to_string().contains("unsupported legacy audit source") => {
// archive/remove the named non-default audit tree, then retry
}
other => other?,
} Prevention
- Inventory all principal directories under the home root before migrating.
- Archive and remove audit data belonging to non-default principals first.
- Remember only the default principal's audit source is migrated — empty extras are fine.
When it happens
Trigger: migrate_legacy_audit when a second (non-default) principal directory under the home root contains .local/audit with at least one entry (fs::read_dir(...).next().is_some(), host_fs.rs:423-429).
Common situations: Machines where astrid was previously run by or for more than one principal, leaving old audit trees; copied home directories containing several principals' data; test fixtures with multiple principal dirs.
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
- unsupported legacy audit source {audit_source}; only the def
- legacy audit retirement source is outside the default princi
- InvalidData
- Unsupported
- legacy audit retirement source is outside the default princi
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/7379c3756e44172b.
Report an issue: GitHub.