astrid-runtime/astrid · error
legacy principal-home entry is not a regular directory
Error message
legacy principal-home entry is not a regular directory: {principal_root} What it means
During the legacy principal-home audit, each entry directly under the home root must be a regular directory (checked with `symlink_metadata`, so symlinks are rejected even if they point to directories). An entry such as a per-principal directory that is a symlink, file, or other non-directory type triggers this InvalidData error, after `verify_no_redirects` already cleared the root path itself.
Solutions
- Replace each offending symlink with a real directory (move the data back or use a bind mount instead of a symlink).
- Remove or relocate stray files that occupy principal-directory names.
- Exclude/fix sync tools (Dropbox, stow, dotbot) that convert directories into symlinks.
- Re-run `verify_no_redirects`/the audit after entries are plain directories.
Example fix
// before: principal dir is a symlink ~/.astrid/principals/alice -> /mnt/secrets/alice // after: real directory rm ~/.astrid/principals/alice mkdir ~/.astrid/principals/alice && cp -a /mnt/secrets/alice/. ~/.astrid/principals/alice/
Defensive patterns
Strategy: validation
Validate before calling
for entry in std::fs::read_dir(home.home_dir())? {
let p = entry?.path();
let md = std::fs::symlink_metadata(&p)?;
if md.file_type().is_symlink() || !md.is_dir() {
eprintln!("{} must be a plain directory", p.display());
}
} Type guard
fn entries_are_plain_dirs(root: &std::path::Path) -> std::io::Result<bool> {
Ok(std::fs::read_dir(root)?.try_all(|e| {
let md = std::fs::symlink_metadata(e.path())?;
Ok(!md.file_type().is_symlink() && md.is_dir())
})?)
} Try / catch
match run_legacy_home_audit(&home) {
Err(e) if e.to_string().contains("entry is not a regular directory") => {
eprintln!("a home entry is a symlink/file; materialize it as a real directory and retry");
}
other => other?,
} Prevention
- Exclude the Astrid home tree from dotfile/sync managers that create symlinks.
- Use bind mounts instead of symlinks to relocate principal directories.
- After restores, verify every entry under the home root is a plain directory before running the audit.
When it happens
Trigger: Running the audit when any entry under the home root (e.g. a principal's directory) is a symlink or a regular file instead of a directory — detected via `symlink_metadata(...).file_type().is_symlink() || !is_dir()`.
Common situations: Dotfile/sync managers symlinking principal directories to a data volume; a corrupt or partial restore leaving a file where a principal directory should be; manually moving principal data to another disk with a symlink left behind.
Related errors
- legacy audit tree is redirected or not a directory
- legacy principal-home root is not a directory
- legacy principal home root is not a regular directory
- legacy principal profile is not a regular file
- Astrid durable media is redirected or not a regular file
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/7c8bf8cd8d178906.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/lib.rs:4143
format!(
"legacy principal-home root is not a directory: {}",
root.display()
),
));
},
Ok(metadata) => metadata,
Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(false),
Err(error) => return Err(error),
};
let root_device = audit_tree_device(&metadata);
let mut default_source_present = false;
astrid_core::platform_fs::verify_no_redirects(&root)?;
for entry in std::fs::read_dir(&root)? {
let entry = entry?;
let principal_root = entry.path();
let principal_metadata = std::fs::symlink_metadata(&principal_root)?;
if principal_metadata.file_type().is_symlink() || !principal_metadata.is_dir() {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"legacy principal-home entry is not a regular directory: {}",
principal_root.display()
),
));
}
if audit_tree_device(&principal_metadata) != root_device {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"legacy principal-home entry crosses a filesystem boundary: {}",
principal_root.display()
),
));
}
astrid_core::platform_fs::verify_no_redirects(&principal_root)?;
let local_root = principal_root.join(".local");View on GitHub (pinned to affd8760f4)