astrid-runtime/astrid · error

legacy capsule authority root is not a regular directory: {}

Error message

legacy capsule authority root is not a regular directory: {}

What it means

active_receipt_files enumerates the legacy capsule authority root, but first verifies via symlink_metadata that the root itself is a plain directory (not a symlink or other file type). If it is not, the library throws this error rather than traversing a redirected or unexpected filesystem object — a security/integrity guard for the authority directory.

Source

Thrown at crates/astrid-capsule-install/src/authority/leftover.rs:233

    }
    if matches.len() == 1 {
        Ok(Some(matches.remove(0)))
    } else {
        Ok(None)
    }
}

fn active_receipt_files(home: &AstridHome) -> anyhow::Result<Vec<PathBuf>> {
    let directory = home.etc_dir().join(AUTHORITY_RECEIPT_DIR);
    let metadata = match fs::symlink_metadata(&directory) {
        Ok(metadata) => metadata,
        Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(Vec::new()),
        Err(error) => {
            return Err(error).with_context(|| format!("inspect {}", directory.display()));
        },
    };
    if metadata.file_type().is_symlink() || !metadata.is_dir() {
        bail!(
            "legacy capsule authority root is not a regular directory: {}",
            directory.display()
        );
    }
    astrid_core::platform_fs::verify_no_redirects(&directory).with_context(|| {
        format!(
            "verify legacy capsule authority root {}",
            directory.display()
        )
    })?;
    let mut paths = Vec::new();
    let mut entries = fs::read_dir(&directory)
        .with_context(|| format!("read legacy capsule authority root {}", directory.display()))?
        .collect::<Result<Vec<_>, _>>()
        .with_context(|| format!("read legacy capsule authority root {}", directory.display()))?;
    entries.sort_by_key(fs::DirEntry::file_name);
    for entry in entries {
        let path = entry.path();

View on GitHub (pinned to affd8760f4)

Solutions

  1. Replace the symlink with a real directory: rm the symlink, mkdir the path, and copy the receipts back
  2. Point ASTRID_HOME (or the workspace config) at a real directory instead of a symlinked or file path
  3. Exclude the authority directory from dotfile-manager symlinking and manage its contents individually
  4. Inspect with ls -la to confirm what exists at the path before recreating it

Example fix

// before
$ ls -l ~/.astrid/authority
authority -> /dotfiles/authority
// after
$ rm ~/.astrid/authority
$ mkdir ~/.astrid/authority
$ cp /dotfiles/authority/* ~/.astrid/authority/
$ astrid migrate
Defensive patterns

Strategy: validation

Validate before calling

let md = std::fs::symlink_metadata(authority_root)?;
if md.is_symlink() || !md.is_dir() {
    anyhow::bail!("authority root must be a real directory: {}", authority_root.display());
}

Type guard

fn is_real_directory(p: &Path) -> bool {
    std::fs::symlink_metadata(p).map(|m| !m.is_symlink() && m.is_dir()).unwrap_or(false)
}

Prevention

When it happens

Trigger: Calling unique_relocated_receipt → active_receipt_files when the authority root path (leftover.rs:233) is a symlink or a regular file instead of a directory: typically the whole ~/.astrid (or authority) directory was symlinked by a dotfile manager, or a file was created at that path.

Common situations: chezmoi/stow managing the .astrid directory via symlink; a misconfigured ASTRID_HOME pointing at a file; leftover junk file created at the authority path by a buggy script.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/1531020df238de39. Report an issue: GitHub.