astrid-runtime/astrid · error · std::io::Error::InvalidData
Astrid home without a layout sentinel is redirected or not a
Error message
Astrid home without a layout sentinel is redirected or not a directory: {} What it means
Thrown by AstridDirs::ensure when the home root has no layout sentinel, and the root itself is either a symlink or not a directory. This guards against redirected or malformed roots being silently initialized as an Astrid home.
Source
Thrown at crates/astrid-core/src/dirs.rs:352
/// # Errors
///
/// Returns an error if directory creation or permission setting fails.
pub fn ensure(&self) -> io::Result<()> {
self.validate_run_dir()?;
let existing_layout = self.layout_version()?;
if let Some(version) = existing_layout.as_deref()
&& version != LEGACY_LAYOUT_VERSION
&& version != LAYOUT_VERSION
{
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("unsupported Astrid home layout version {version:?}"),
));
}
if existing_layout.is_none() {
match std::fs::symlink_metadata(self.root()) {
Ok(metadata) if metadata.file_type().is_symlink() || !metadata.is_dir() => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"Astrid home without a layout sentinel is redirected or not a directory: {}",
self.root().display()
),
));
},
Ok(_) => {},
Err(error) if error.kind() == io::ErrorKind::NotFound => {},
Err(error) => return Err(error),
}
}
let mut dirs = Vec::<PathBuf>::new();
if existing_layout.as_deref() == Some(LEGACY_LAYOUT_VERSION) {
dirs.extend([
self.etc_dir(),
self.hooks_dir(),
self.var_dir(),View on GitHub (pinned to affd8760f4)
Solutions
- Replace the symlink/file at the home path with a real directory and re-run ensure
- Remove the stale non-directory entry and re-initialize the home
- If redirection is intended, point ASTRID_HOME directly at the target directory
Example fix
// before: root is a symlink ln -s /mnt/volume/.astrid ~/.astrid // after: use the target path directly export ASTRID_HOME=/mnt/volume/.astrid
Defensive patterns
Strategy: validation
Validate before calling
let md = std::fs::symlink_metadata(&home_path)?; assert!(md.is_dir() && !md.file_type().is_symlink(), "home must be a real directory");
Type guard
fn is_real_dir(p: &std::path::Path) -> bool {
std::fs::symlink_metadata(p).map(|m| m.is_dir() && !m.file_type().is_symlink()).unwrap_or(false)
} Try / catch
match dirs.ensure() {
Err(e) if e.to_string().contains("redirected or not a directory") => {
eprintln!("Home path is a symlink or non-directory; fix the path");
},
other => other?,
} Prevention
- Don't symlink the Astrid home; point ASTRID_HOME at the target instead
- Check for leftover files at the home path after uninstalls
- Run symlink_metadata checks in deployment scripts
When it happens
Trigger: Calling ensure on a path where the root is a symlink (e.g. redirecting the home elsewhere) or a regular file/socket, with no layout sentinel present.
Common situations: Users symlinking their Astrid home to another volume, a stale file occupying the expected home path, or a partially deleted home directory.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- layout migration source contains a redirect: {}
- legacy state source is redirected or not a directory: {}
- leftover capsule authority receipt is not a regular file: {}
- legacy capsule authority root is not a regular directory: {}
- legacy capsule authority root contains a non-regular entry:
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/3656a8845281fa6a.
Report an issue: GitHub.