astrid-runtime/astrid · error
legacy principal-home root is not a directory: {}
Error message
legacy principal-home root is not a directory: {} What it means
preflight_legacy_audit_sources (non-Unix host path) validates that the principal home root is a plain directory before scanning it for legacy audit sources. If symlink_metadata reports the root is a symlink or not a directory, the migration aborts with InvalidData, because following a redirected home root could make the importer read or retire data outside the intended boundary.
Source
Thrown at crates/astrid-kernel/src/legacy_migration_barrier/host_fs.rs:362
child.display()
),
));
}
fs::remove_file(child).map_err(io::Error::other)
}
/// Validate the released audit-source boundary on every native host. Unix
/// adds device and mount checks; all hosts retain no-follow, regular-entry,
/// and default-principal-only checks before the audit importer opens a source.
#[cfg(not(unix))]
pub(super) fn preflight_legacy_audit_sources(
home: &AstridHome,
default_source: &Path,
) -> io::Result<bool> {
let root = home.home_dir();
let metadata = match fs::symlink_metadata(&root) {
Ok(metadata) if metadata.file_type().is_symlink() || !metadata.is_dir() => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"legacy principal-home root is not a directory: {}",
root.display()
),
));
},
Ok(metadata) => metadata,
Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(false),
Err(error) => return Err(error),
};
let root_device = device_id(&metadata);
let mut default_source_present = false;
astrid_core::platform_fs::verify_no_redirects(&root)?;
for entry in fs::read_dir(&root).map_err(io::Error::other)? {
let principal_root = entry.map_err(io::Error::other)?.path();
let principal_metadata = fs::symlink_metadata(&principal_root).map_err(io::Error::other)?;
if principal_metadata.file_type().is_symlink() || !principal_metadata.is_dir() {View on GitHub (pinned to affd8760f4)
Solutions
- Replace the symlink at the home root with a real directory (mv the target contents back or use a bind mount).
- Remove/rename the stray file occupying the home path and recreate it as a directory.
- Point the home configuration (env var/config) at the actual directory location instead of a symlink.
- Re-run migrate_legacy_audit once home.home_dir() resolves to a physical directory.
Example fix
// before: dotfile-manager symlink /home/u/.astrid -> /dotfiles/astrid // after $ rm /home/u/.astrid && mkdir /home/u/.astrid && cp -a /dotfiles/astrid/. /home/u/.astrid/
Defensive patterns
Strategy: validation
Validate before calling
fn home_root_ok(home_dir: &std::path::Path) -> std::io::Result<bool> {
match std::fs::symlink_metadata(home_dir) {
Ok(m) => Ok(!m.file_type().is_symlink() && m.is_dir()),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(true), // tolerated
Err(e) => Err(e),
}
} Type guard
fn is_plain_dir(m: &std::fs::Metadata) -> bool {
!m.file_type().is_symlink() && m.is_dir()
} Try / catch
match result {
Err(e) if e.kind() == std::io::ErrorKind::InvalidData && e.to_string().contains("root is not a directory") => {
// fix the home path (de-symlink / recreate as directory), then retry
}
other => other?,
} Prevention
- Do not symlink the astrid home root; use real directories.
- If redirection is needed, mount rather than symlink so the path is a physical directory.
- Validate the configured home path with symlink_metadata before running migrations.
When it happens
Trigger: Calling migrate_legacy_audit when the principal home directory path (home.home_dir()) is itself a symlink, a regular file, or another non-directory entry (host_fs.rs:361). Note NotFound is tolerated and returns Ok(false), so only existing-but-wrong types trigger this.
Common situations: Users who symlink their home directory to another location (common with dotfile managers); a file accidentally created at the home path; misconfigured ASTRID home env var pointing at a file.
Related errors
- legacy principal-home entry is not a regular directory: {}
- legacy capsule directory is not a regular directory: {}
- legacy capsule entry is not a regular directory: {}
- legacy env/secret path is not a regular directory: {}
- legacy REPL history is not a regular file: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/08f53c5f2db288cc.
Report an issue: GitHub.