astrid-runtime/astrid · error

capsule target has no parent

Error message

capsule target has no parent

What it means

publish_directory_package stages a verified package via a temp materialization directory created inside the PARENT of the target directory (so the rename/stage is same-filesystem). If target_dir has no parent (i.e. it is a filesystem root like '/' or an empty relative path resolved to root), the publish cannot create its staging directory and this error is raised.

Source

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

        )
    })?;
    let authority = serde_json::to_vec_pretty(&durable_authority)
        .context("serialize installed capsule authority receipt")?;
    let registry = store.capsules();
    let owner = StateOwner::Principal(uid);
    let id = authority_capsule_id(&authority)?;
    let expected = registry
        .get_snapshot(&owner, &id)?
        .map_or(CapsuleInstallExpectation::Absent, |snapshot| {
            CapsuleInstallExpectation::Generation(snapshot.generation())
        });
    let package = CapsulePackage::new(archive, metadata, authority);
    let materialization = tempfile::Builder::new()
        .prefix(".capsule-materialization-")
        .tempdir_in(
            target_dir
                .parent()
                .ok_or_else(|| anyhow::anyhow!("capsule target has no parent"))?,
        )
        .context("stage verified durable capsule materialization")?;
    let staged_target = materialization.path().join("package");
    materialize_capsule_package(&package, &staged_target)
        .context("stage verified durable capsule package")?;

    // Storage-backed installs initially assemble a lifecycle workspace that
    // intentionally omits the WASM component. Replace it with the complete
    // verified package before publication so an immediately triggered live
    // reload sees the same bytes that a restart would rematerialize.
    let previous_target = materialization.path().join("previous");
    fs::rename(target_dir, &previous_target)
        .context("stage incomplete capsule install cache for replacement")?;
    if let Err(error) = fs::rename(&staged_target, target_dir) {
        let _ = fs::rename(&previous_target, target_dir);
        return Err(error).context("publish verified capsule materialization");
    }

View on GitHub (pinned to affd8760f4)

Solutions

  1. Pass a real capsule target directory that has a parent, e.g. ~/.astrid/capsules/<name> rather than / .
  2. Fix path-building code that normalizes the target down to the root; keep at least one directory component.
  3. Validate the target path before publishing (target.is_absolute() && target.parent().is_some()).
  4. If publishing to a mount, use a subdirectory of the mount instead of the mount root.

Example fix

// before
publish_directory_package(store, registry, "/", /* ... */)?;
// after
let target = PathBuf::from("/var/lib/capsules/my-capsule");
publish_directory_package(store, registry, &target, /* ... */)?;
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_publishable_target(target: &std::path::Path) -> anyhow::Result<()> {
    if target.parent().is_none() {
        anyhow::bail!("target {:?} must have a parent directory", target);
    }
    Ok(())
}

Prevention

When it happens

Trigger: Calling publish_directory_package with target_dir = '/' or another path whose parent() returns None — e.g. publishing directly to a mount point root or passing an empty/normalized-to-root target path.

Common situations: Misconfigured install target pointing at the filesystem root; a script building the target path with join/normalize logic that strips all components; tests passing Path::new("/").

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