astrid-runtime/astrid · error

opaque capsule assets cannot be symlinks: {}

Error message

opaque capsule assets cannot be symlinks: {}

What it means

In the FUSE storage provider's hidden service mode, run_launch computes the parent-challenge for the readiness handshake via storage_provider_service_ready_challenge and maps any error it returns into an anyhow error using the error's Display text ('{error}'). It indicates the launch handshake inputs (parent token, mount id, paths) failed challenge derivation, so the service cannot prove itself to the parent process.

Source

Thrown at crates/astrid-build/src/archiver.rs:50

        if metadata.file_type().is_symlink() {
            anyhow::bail!(
                "opaque capsule asset directories cannot be symlinks: {}",
                root.display()
            );
        }
        if !metadata.is_dir() {
            anyhow::bail!("opaque asset path must be a directory: {}", root.display());
        }
        let mut pending = vec![root];
        while let Some(dir) = pending.pop() {
            for entry in fs::read_dir(&dir)
                .with_context(|| format!("Failed to read asset directory: {}", dir.display()))?
            {
                let entry = entry?;
                let path = entry.path();
                let file_type = entry.file_type()?;
                if file_type.is_symlink() {
                    anyhow::bail!(
                        "opaque capsule assets cannot be symlinks: {}",
                        path.display()
                    );
                }
                if file_type.is_dir() {
                    pending.push(path);
                } else if file_type.is_file() {
                    files.push(path);
                }
            }
        }
    }
    files.sort();
    Ok(files)
}

/// Packages a set of files and directories into a single `.capsule` (tar.gz) archive.
pub(crate) fn pack_capsule_archive(

View on GitHub (pinned to affd8760f4)

Solutions

  1. Inspect the inner error text to see which challenge input failed, then fix the parent-side launch payload accordingly.
  2. Ensure launch.parent.token is a valid, non-empty token produced by storage_provider_service_ready_challenge's counterpart on the parent side.
  3. Verify control_path, resource_path and callback_path are absolute, valid paths and mount_id is a well-formed UUID.

Example fix

// before
let challenge = storage_provider_service_ready_challenge(
    &launch.parent.token, /* token from hand-built launch JSON */ ...
).map_err(|error| anyhow::anyhow!(error))?;
// after
// construct the launch via the parent SDK so the token is derived from the same inputs
let launch = StorageProviderServiceLaunchV1::build(&lease, &parent)?;
let challenge = storage_provider_service_ready_challenge(
    &launch.parent.token, ...
).map_err(|error| anyhow::anyhow!(error))?;
Defensive patterns

Strategy: try-catch

Validate before calling

fn launch_inputs_ok(launch: &StorageProviderServiceLaunchV1) -> bool {
    !launch.parent.token.is_empty()
        && launch.lease.mount_id.as_uuid() != uuid::Uuid::nil()
        && !launch.control_path.as_os_str().is_empty()
}

Try / catch

match run_launch(launch).await {
    Err(e) => { eprintln!("FUSE launch failed: {e:#}"); std::process::exit(1); },
    Ok(()) => {},
}

Prevention

When it happens

Trigger: run (FUSE service mode) receives a StorageProviderServiceLaunchV1 on stdin, passes validate_launch, then storage_provider_service_ready_challenge returns Err — e.g. malformed or empty parent token, or invalid path/UUID inputs — and run_launch propagates it verbatim.

Common situations: Parent process passed an empty or wrongly-encoded parent.token; control/resource/callback paths contain invalid characters or are empty; mount_id UUID serialization mismatch between parent and provider versions.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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