astrid-runtime/astrid · error

legacy source contains a special entry: {}

Error message

legacy source contains a special entry: {}

What it means

snapshot_path_with_access can only fingerprint regular files and directories. If the top-level legacy source is neither (fifo, socket, device node, other special file), it cannot be hashed or counted as source entries, so the library raises InvalidData. Note validate_source_entry has already run for the path itself, so this fires when the top-level entry type is admissible to earlier checks but not a file/dir for snapshotting.

Source

Thrown at crates/astrid-kernel/src/legacy_migration_barrier/host_fs.rs:642

        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!("legacy source is an active mount: {}", path.display()),
        ));
    }
    let device = device_id(&metadata);
    let mut hasher = blake3::Hasher::new_derive_key("astrid layout component source v1");
    let mut identity = SourceInventory::default();
    if metadata.is_file() {
        // A top-level regular file is itself one source entry.  Directory
        // snapshots count children in `snapshot_dir`; keeping the same
        // cardinality here lets retirement bind a single-file source to the
        // exact preflight manifest as well.
        identity.entries = SourceCount::new(1);
        read_regular_file(path, &mut hasher, &mut identity)?;
    } else if metadata.is_dir() {
        snapshot_dir(path, path, device, access, &mut hasher, &mut identity)?;
    } else {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!("legacy source contains a special entry: {}", path.display()),
        ));
    }
    SourceIdentity::present(
        SourceDigest::from_blake3(hasher.finalize()),
        identity.entries,
        identity.bytes,
    )
    .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))
}

/// Validate one regular-file source using the same no-follow, private,
/// same-device, and mount checks as recursive snapshots.  Distro lock files
/// keep their component-owned digest format, so they use this structural
/// check instead of the generic tree hash.
pub(super) fn validate_source_path(path: &Path) -> io::Result<()> {
    let metadata = fs::symlink_metadata(path)?;

View on GitHub (pinned to affd8760f4)

Solutions

  1. Stop the process owning the special file and remove it from the legacy source path.
  2. Restore the expected regular file or directory at that path (from backup or by re-creating the legacy layout).
  3. Re-run the migration/snapshot once the source is a plain file or directory.

Example fix

// before
prw-r--r-- legacy-ctl (fifo) at the component source path
// after
rm legacy-ctl
# restore or create a regular file/directory at the path, then re-run
Defensive patterns

Strategy: validation

Validate before calling

match std::fs::symlink_metadata(&source) {
    Ok(m) if m.is_file() || m.is_dir() => {},
    Ok(_) => eprintln!("{} is a special file; remove it first", source.display()),
    Err(_) => {},
}

Type guard

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

Try / catch

if let Err(e) = snapshot_path(&source) {
    if e.to_string().contains("special entry") {
        // remove/replace the special file at the source path, then retry
    }
}

Prevention

When it happens

Trigger: Calling snapshot_path or snapshot_owner_controlled_path on a legacy source path that resolves to a special file rather than a regular file or directory; the final else-branch of the file/dir dispatch.

Common situations: A legacy component path occupied by a socket or pipe left by an old daemon; a device node appearing where data used to live; corrupted layout after a crashed tool.

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/0119e15135850381. Report an issue: GitHub.