astrid-runtime/astrid · error

legacy capsule entry has no name

Error message

legacy capsule entry has no name

What it means

copy_legacy_tree recursively copies a legacy capsule directory tree, and each entry must have a file name to compute its destination path. When an entry has no file name (e.g. a path ending in '..' or an unusual filesystem entry), the library throws because it cannot determine where to copy the entry.

Solutions

  1. Inspect the legacy capsule directory for odd entries (dotdot paths, mount points, nameless entries) and remove or rename them.
  2. Rebuild the legacy capsule tree with a clean directory layout and rerun the copy/ canonicalization.
  3. Copy the tree manually into the expected layout if the source filesystem produces pathological entries.
Defensive patterns

Strategy: try-catch

Try / catch

match copy_legacy_tree(&src, &dst) {
    Ok(()) => {},
    Err(e) if e.to_string().contains("no name") => {
        eprintln!("legacy tree has a nameless entry: {e:#}");
        // inspect and clean the source directory, then retry
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: copy_legacy_tree (or canonical_legacy_archive through it) iterates read_dir_sorted(source) and encounters a directory entry whose file_name() is None — the path component ends with .. or is otherwise nameless.

Common situations: Legacy capsule directories containing malformed entries; paths produced by symlinks or mount points like '..' surviving into the directory listing; filesystem oddities when migrating old capsule layouts.

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

Appendix: source

Thrown at crates/astrid-capsule-install/src/storage.rs:697

            );
        }
        let source = home.wit_store_dir().join(format!("{hash}.wit"));
        let destination = staging.path().join("wit").join(relative);
        if let Some(parent) = destination.parent() {
            fs::create_dir_all(parent)?;
        }
        fs::copy(&source, &destination)
            .with_context(|| format!("restore content-addressed WIT blob {hash}"))?;
    }
    canonical_capsule_archive(staging.path())
}

fn copy_legacy_tree(source: &Path, destination: &Path) -> anyhow::Result<()> {
    fs::create_dir_all(destination)?;
    for (path, metadata) in read_dir_sorted(source)? {
        let relative = path
            .file_name()
            .ok_or_else(|| anyhow::anyhow!("legacy capsule entry has no name"))?;
        let destination = destination.join(relative);
        if metadata.file_type().is_symlink() {
            bail!("legacy capsule contains symlink {}", path.display());
        }
        if metadata.is_dir() {
            copy_legacy_tree(&path, &destination)?;
        } else if metadata.is_file() {
            let name = path.file_name().and_then(|name| name.to_str());
            if matches!(name, Some("meta.json" | "authority.json" | ".env.json")) {
                continue;
            }
            fs::copy(path, destination)?;
        } else {
            bail!("legacy capsule contains special file {}", path.display());
        }
    }
    Ok(())
}

View on GitHub (pinned to affd8760f4)