astrid-runtime/astrid · error

legacy capsule authority root contains a non-regular entry:

Error message

legacy capsule authority root contains a non-regular entry: {}

What it means

While enumerating entries of the legacy authority root for status reporting, legacy_authority_receipt_status requires each entry (via fs::symlink_metadata) to be a regular file. Any symlink, subdirectory, or special file triggers this error so status is never computed from redirected or non-file entries.

Source

Thrown at crates/astrid-capsule-install/src/authority/status.rs:73

        )
    })?;

    let permitted = workspace_targets
        .iter()
        .map(|target| authority_paths(home, target).map(|paths| paths.active))
        .collect::<anyhow::Result<BTreeSet<_>>>()?;
    let mut status = LegacyAuthorityReceiptStatus::default();
    let mut entries = std::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(std::fs::DirEntry::file_name);
    for entry in entries {
        let path = entry.path();
        let metadata = std::fs::symlink_metadata(&path)
            .with_context(|| format!("inspect legacy capsule authority {}", path.display()))?;
        if metadata.file_type().is_symlink() || !metadata.is_file() {
            bail!(
                "legacy capsule authority root contains a non-regular entry: {}",
                path.display()
            );
        }
        let Some(name) = path.file_name().and_then(|name| name.to_str()) else {
            bail!(
                "legacy capsule authority entry has a non-UTF-8 name: {}",
                path.display()
            );
        };
        if name.ends_with(".pending") {
            status.pending.push(path);
        } else if name.ends_with(".previous") {
            status.previous.push(path);
        } else if !path
            .extension()
            .is_some_and(|extension| extension.eq_ignore_ascii_case("json"))
            || !permitted.contains(&path)

View on GitHub (pinned to affd8760f4)

Solutions

  1. Find the offending entry with find <authority-root> ! -type f and move non-files out of the directory
  2. Replace symlinked receipt entries with real file copies
  3. Keep the authority directory flat: only regular receipt files belong there
  4. Re-run the status command after cleaning to confirm

Example fix

// before
~/.astrid/authority/archive/ (subdirectory)
// after
$ mv ~/.astrid/authority/archive ~/astrid-archive/
$ astrid authority status
Defensive patterns

Strategy: validation

Validate before calling

let bad: Vec<_> = std::fs::read_dir(root)?.filter_map(Result::ok)
    .filter(|e| !std::fs::symlink_metadata(e.path()).map(|m| m.is_file()).unwrap_or(false))
    .map(|e| e.path()).collect();
if !bad.is_empty() { eprintln!("move these out first: {:?}", bad); }

Type guard

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

Prevention

When it happens

Trigger: Calling legacy_capsule_authority_status (or its test callers) when any entry in the authority root (status.rs:73) is a symlink/directory/FIFO — e.g. a stray subdirectory or a symlinked receipt left by a dotfile manager.

Common situations: Manual cleanup left a backup subdirectory inside the authority root; receipts symlinked into a synced folder; a socket or pipe created by another tool in that directory.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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