astrid-runtime/astrid · error · io::Error
layout path has no existing directory ancestor: {}
Error message
layout path has no existing directory ancestor: {} What it means
verify_existing_ancestor walks up the parent chain of a home path looking for an existing directory ancestor; if it exhausts the chain (candidate has no parent), it returns InvalidData. In practice this means the Astrid home path is so incomplete that not even a root-adjacent ancestor exists — the path is effectively empty or malformed, so preflight cannot establish a real filesystem anchor.
Source
Thrown at crates/astrid-core/src/dirs_layout.rs:437
}
fn verify_existing_ancestor(path: &Path) -> io::Result<()> {
let mut candidate = path;
loop {
match std::fs::symlink_metadata(candidate) {
Ok(metadata) if metadata.file_type().is_symlink() || !metadata.is_dir() => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"layout path is redirected or not a directory: {}",
candidate.display()
),
));
},
Ok(_) => return crate::platform_fs::verify_no_redirects(candidate),
Err(error) if error.kind() == io::ErrorKind::NotFound => {
candidate = candidate.parent().ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidData,
format!(
"layout path has no existing directory ancestor: {}",
path.display()
),
)
})?;
},
Err(error) => return Err(error),
}
}
}
fn path_entry_present(path: &Path) -> io::Result<bool> {
match std::fs::symlink_metadata(path) {
Ok(_) => Ok(true),
Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
Err(error) => Err(error),View on GitHub (pinned to affd8760f4)
Solutions
- Verify the AstridHome root path is absolute, non-empty, and points where you intend
- Create the home root with std::fs::create_dir_all before invoking the migration APIs
- Fix path-construction bugs that produce empty or root-only paths (e.g. joining onto an empty base)
- Run the normal AstridHome::ensure initialization first so the directory skeleton exists before migration preflight runs
Example fix
// before: empty home path
let home = AstridHome::open(Path::new("")).unwrap();
home.begin_layout_v2_migration(&target)?; // InvalidData: no existing ancestor
// after
let root = Path::new("/var/lib/astrid");
std::fs::create_dir_all(root)?;
let home = AstridHome::open(root).unwrap();
home.begin_layout_v2_migration(&target)?; Defensive patterns
Strategy: validation
Validate before calling
let root = home.root();
if root.as_os_str().is_empty() || !root.is_absolute() {
return Err(anyhow!("home root must be a non-empty absolute path"));
}
std::fs::create_dir_all(root)?; Type guard
fn is_usable_root(p: &Path) -> bool {
!p.as_os_str().is_empty() && p.is_absolute()
} Try / catch
match home.begin_layout_v2_migration(&target) {
Err(e) if e.to_string().contains("no existing directory ancestor") => {
// fix the home path and create the directory tree before retrying
},
r => r?,
} Prevention
- Validate home paths at config load: absolute and non-empty
- Create the root with create_dir_all before any migration call
- Check path-construction code for empty-base join bugs
- Run AstridHome::ensure before driving migration APIs directly
When it happens
Trigger: Calling begin_layout_v2_migration or complete_layout_v2 with a home root whose entire path chain is missing (candidate.parent() eventually returns None, e.g. root or relative path ""), or a path so broken no existing ancestor can be found.
Common situations: Passing an empty or malformed path as the Astrid home; running in a chroot/container where the home's parent directories were never created; constructing the home path programmatically with a bug that yields "/" or an empty PathBuf.
Related errors
- layout migration receipt destination path does not match the
- unsupported Astrid home layout version {other:?}
- layout-two home contains legacy state without a completion r
- layout migration receipt does not match its intent or destin
- insufficient free space for layout migration: need {required
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/03a6dabbd2520e57.
Report an issue: GitHub.