astrid-runtime/astrid · error

capsule content cannot contain a directory symlink

Error message

capsule content cannot contain a directory symlink: {}

What it means

Fired by collect_directory_records when a symlink inside the capsule resolves to a directory. Only symlinks to regular files are permitted, since directory symlinks would bypass per-file content verification.

Solutions

  1. Remove the directory symlink and place the directory contents physically in the tree
  2. Rebuild the capsule flattening the symlink
  3. Point the capsule at a fixed snapshot of the directory
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/astrid-build/src/artifact.rs:474 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at crates/astrid-build/src/artifact.rs:474

    let mut entries = std::fs::read_dir(current)
        .with_context(|| format!("failed to read capsule directory {}", current.display()))?
        .collect::<Result<Vec<_>, _>>()?;
    entries.sort_unstable_by_key(std::fs::DirEntry::file_name);
    for entry in entries {
        let path = entry.path();
        let file_type = entry.file_type()?;
        if file_type.is_symlink() {
            let resolved = std::fs::canonicalize(&path)
                .with_context(|| format!("failed to resolve capsule symlink {}", path.display()))?;
            if !resolved.starts_with(canonical_root) {
                bail!(
                    "capsule symlink resolves outside its source tree: {}",
                    path.display()
                );
            }
            let metadata = std::fs::metadata(&resolved)?;
            if !metadata.is_file() {
                bail!(
                    "capsule content cannot contain a directory symlink: {}",
                    path.display()
                );
            }
            let relative = path.strip_prefix(root)?;
            let normalized = normalize_relative_path(relative)?;
            let mut file = File::open(&resolved)?;
            records.push(hash_reader(normalized, metadata.len(), &mut file)?);
            continue;
        }
        if file_type.is_dir() {
            collect_directory_records(root, canonical_root, &path, records, envelope)?;
            continue;
        }
        if !file_type.is_file() {
            bail!(
                "capsule content contains a special file: {}",
                path.display()

View on GitHub (pinned to affd8760f4)