astrid-runtime/astrid · error · io::Error
InvalidData
InvalidData
Error message
legacy dedicated source is not a regular directory: {} What it means
tighten_dedicated_tree tightens permissions on a legacy dedicated directory tree. The path must be a real directory; if symlink_metadata reports a symlink or non-directory, the function aborts with this InvalidData error because tightening a link or file would be meaningless or unsafe. A NotFound path is tolerated and returns Ok.
Solutions
- Replace the symlink/file at the reported path with a real directory
- Copy the link target's contents into a genuine directory and remove the link
- Remove the stray file if it is leftover debris, then re-run tightening
- Fix the tooling that converted the directory into a link
Example fix
// before: legacy dedicated path is a symlink to /tmp/legacy // after rm <legacy-dedicated-path> mkdir <legacy-dedicated-path> cp -a /tmp/legacy/. <legacy-dedicated-path>/
Defensive patterns
Strategy: validation
Validate before calling
match std::fs::symlink_metadata(path) {
Ok(md) if md.file_type().is_symlink() || !md.is_dir() => { /* replace with real dir */ }
Ok(_) => {}
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} // tolerated
Err(e) => return Err(e),
} Type guard
fn is_plain_dir(path: &std::path::Path) -> bool {
std::fs::symlink_metadata(path).map(|m| !m.file_type().is_symlink() && m.is_dir()).unwrap_or(false)
} Try / catch
if let Err(e) = tighten_legacy_dedicated_directories(&home) {
if e.to_string().contains("not a regular directory") {
eprintln!("replace the path named in the error with a real directory");
}
} Prevention
- Never symlink legacy dedicated directories (e.g. to /tmp or another volume)
- Pre-scan the tree with symlink_metadata before tightening
- Remove stray files left by partial cleanups
When it happens
Trigger: tighten_dedicated_tree (called by tighten_legacy_dedicated_directories, including recursively) encounters a path whose symlink_metadata shows is_symlink() or !is_dir(); NotFound is silently skipped, anything else non-directory errors.
Common situations: A legacy tmp/dedicated directory was replaced by a symlink to /tmp or shared storage; a file was created where the directory is expected; partial cleanup left a broken structure.
Related errors
- layout migration destination is redirected or not a regular…
- layout migration source contains a redirect
- layout migration source is redirected or not a directory
- legacy audit source is not a regular directory
- legacy audit tree is redirected or not a directory
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/40514f7225acaa99.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/legacy_migration_barrier/legacy_tmp.rs:42
for path in [
principal.kv_dir(),
principal.tokens_dir(),
principal.tmp_dir(),
] {
tighten_dedicated_tree(&path)?;
}
}
Ok(())
}
fn tighten_dedicated_tree(path: &Path) -> io::Result<()> {
let metadata = match fs::symlink_metadata(path) {
Ok(metadata) => metadata,
Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(()),
Err(error) => return Err(error),
};
if metadata.file_type().is_symlink() || !metadata.is_dir() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"legacy dedicated source is not a regular directory: {}",
path.display()
),
));
}
astrid_core::platform_fs::verify_no_redirects(path)?;
#[cfg(unix)]
{
use std::os::unix::fs::MetadataExt as _;
if metadata.uid() != nix::unistd::getuid().as_raw() {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!(
"legacy dedicated source is not owned by the current user: {}",
path.display()
),View on GitHub (pinned to affd8760f4)