astrid-runtime/astrid · error

legacy audit tree contains a special file: {child}

Error message

legacy audit tree contains a special file: {child}

What it means

Thrown during audit-tree validation when a child entry is neither a regular file nor a directory — e.g. a device node, FIFO, or socket. The tree may only contain plain files (which are additionally checked by verify_no_redirects) and directories, so special files are rejected as InvalidData with the offending path.

Source

Thrown at crates/astrid-kernel/src/lib.rs:4360

        let child_metadata = std::fs::symlink_metadata(&child)?;
        if child_metadata.file_type().is_symlink()
            || audit_tree_device(&child_metadata) != root_device
            || audit_mountpoint(&child)?
        {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                format!(
                    "legacy audit tree contains a redirect or boundary: {}",
                    child.display()
                ),
            ));
        }
        if child_metadata.is_dir() {
            validate_audit_tree(&child, root_device)?;
        } else if child_metadata.is_file() {
            astrid_core::platform_fs::verify_no_redirects(&child)?;
        } else {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                format!(
                    "legacy audit tree contains a special file: {}",
                    child.display()
                ),
            ));
        }
    }
    Ok(())
}

#[cfg(unix)]
fn delete_audit_tree(path: &Path, root_device: u64) -> std::io::Result<()> {
    validate_audit_tree(path, root_device)?;
    for entry in std::fs::read_dir(path)? {
        let child = entry?.path();
        let metadata = std::fs::symlink_metadata(&child)?;
        if metadata.is_dir() {

View on GitHub (pinned to affd8760f4)

Solutions

  1. Find the special file reported in the error and move it out of the audit tree
  2. Recreate the entry as a regular file or directory if it should hold audit data
  3. If a socket must live there, reconfigure the daemon to place it outside the audit tree
  4. Audit the directory with `find <tree> ! -type f ! -type d` to catch all offending entries

Example fix

// before: daemon socket inside audit tree
/var/lib/app/audit/daemon.sock
// after: move socket elsewhere
/var/run/app/daemon.sock
Defensive patterns

Strategy: validation

Validate before calling

for entry in std::fs::read_dir(audit_root)? {
    let md = entry?.metadata()?;
    if !md.is_dir() && !md.is_file() {
        eprintln!("special file in audit tree");
    }
}

Type guard

fn is_file_or_dir(md: &std::fs::Metadata) -> bool { md.is_dir() || md.is_file() }

Try / catch

if let Err(e) = validate_audit_tree(root, dev) {
    if e.kind() == std::io::ErrorKind::InvalidData { eprintln!("audit tree invalid: {e}"); }
}

Prevention

When it happens

Trigger: Running the audit-tree validation when a child path under the tree is a character/block device, named pipe, unix socket, or any other non-regular, non-directory file type.

Common situations: Someone placed a unix socket (e.g. a daemon socket) inside the audit directory; a device node was bind-mounted or mknod'ed into the tree; copy tools accidentally recreated FIFOs.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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