astrid-runtime/astrid · error

legacy capsule WIT path is not relative: {}

Error message

legacy capsule WIT path is not relative: {}

What it means

Raised by canonical_legacy_archive when migrating a legacy native capsule: a WIT file's path, computed relative to the legacy home directory, contains a parent-directory (..) or root (/) component. The library refuses to place non-relative paths into the staging archive because they could escape the staging directory or produce an invalid package layout. This is a path-safety check during legacy capsule migration.

Source

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

        let destination = staging.path().join(component_path);
        if let Some(parent) = destination.parent() {
            fs::create_dir_all(parent)?;
        }
        fs::copy(&wasm, &destination).with_context(|| {
            format!("restore content-addressed WASM blob for {}", wasm.display())
        })?;
    }
    for (relative, hash) in &meta.wit_files {
        let relative = Path::new(relative);
        if relative.is_absolute()
            || relative.components().any(|part| {
                matches!(
                    part,
                    std::path::Component::ParentDir | std::path::Component::RootDir
                )
            })
        {
            bail!(
                "legacy capsule WIT path is not relative: {}",
                relative.display()
            );
        }
        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)? {

View on GitHub (pinned to affd8760f4)

Solutions

  1. Inspect the legacy capsule's WIT store metadata and fix the recorded path so it is relative to the legacy home directory (no leading `/`, no `..` segments).
  2. Reinstall or re-publish the affected WIT package into the legacy capsule so the store entry is regenerated with a canonical relative path.
  3. If the legacy state is corrupt, remove the affected legacy capsule and migrate it fresh from its original source.

Example fix

// before: legacy metadata stores an absolute WIT path
"wit_path": "/home/alice/.astrid/wit/abc123.wit"

// after: store path relative to the legacy home/wit store root
"wit_path": "abc123.wit"
Defensive patterns

Strategy: validation

Validate before calling

fn wit_path_is_relative(p: &Path) -> bool {
    !p.is_absolute()
        && p.components().all(|c| matches!(c, std::path::Component::Normal(_)))
}

Type guard

fn is_clean_relative(p: &Path) -> bool {
    p.is_relative() && !p.components().any(|c| c.as_os_str() == "..")
}

Try / catch

match migrate_native_capsules_with_report(...) {
    Err(e) if e.to_string().contains("not relative") => fix_legacy_wit_paths(),
    other => other?,
}

Prevention

When it happens

Trigger: Calling migrate_native_capsules_with_report on a legacy capsule whose wit_store metadata or recorded relative WIT path contains `..`, is absolute, or otherwise fails the relative-path component check; typically from tampered or hand-edited legacy metadata rather than normal installs.

Common situations: Legacy capsule state directories copied between machines with altered layout; manually edited or corrupted legacy WIT store entries; migration scripts that rewrote paths with absolute prefixes or `..` segments.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


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