astrid-runtime/astrid · error

unexpected capsule metadata response: {other:?}

Error message

unexpected capsule metadata response: {other:?}

What it means

When the kernel replies to GetCapsuleMetadata with a response that is neither CapsuleMetadata nor Error, the CLI treats it as a protocol violation and bails with a debug dump of the unexpected variant. This indicates the kernel/CLI speak different protocol versions or the response was routed incorrectly.

Source

Thrown at crates/astrid-cli/src/commands/init_grant.rs:305

/// Reuse a fresh lock only when its installed state still verifies. A current
/// distro id/version with stale or incomplete install provenance falls through
/// to the normal checked install path so init can regenerate the lock.
pub(super) async fn validated_grant_set_for_reuse(
    target: &PrincipalId,
    locked: &[super::LockedCapsule],
) -> Option<Vec<String>> {
    if target != &crate::principal::current() {
        return None;
    }
    let result = async {
        let mut client = crate::socket_client::connect_kernel_for_workspace(None).await?;
        let entries = match client
            .request(astrid_core::kernel_api::KernelRequest::GetCapsuleMetadata)
            .await?
        {
            astrid_core::kernel_api::KernelResponse::CapsuleMetadata(entries) => entries,
            astrid_core::kernel_api::KernelResponse::Error(message) => bail!(message),
            other => bail!("unexpected capsule metadata response: {other:?}"),
        };
        let mut installed = Vec::with_capacity(locked.len());
        for capsule in locked {
            let expected = CapsuleId::new(capsule.name.clone())?;
            let entry = entries
                .iter()
                .find(|entry| entry.name == capsule.name)
                .ok_or_else(|| {
                    anyhow::anyhow!(
                        "Distro.lock capsule '{}' is absent from the daemon registry",
                        capsule.name
                    )
                })?;
            if !capsule.version.is_empty() && entry.version != capsule.version {
                bail!(
                    "Distro.lock capsule '{}' expects version {}, but the daemon registry reports {}",
                    capsule.name,
                    capsule.version,

View on GitHub (pinned to affd8760f4)

Solutions

  1. Upgrade (or align) the CLI and kernel so GetCapsuleMetadata returns CapsuleMetadata.
  2. Restart the kernel process and retry.
  3. Inspect the {other:?} debug output to identify which variant was returned and trace why.
  4. Report/patch the kernel handler if a new response type must be supported by the CLI.
Defensive patterns

Strategy: type-guard

Validate before calling

// pre-flight protocol check
match client.request(KernelRequest::Ping).await? {
    KernelResponse::Pong => {},
    other => eprintln!("kernel protocol mismatch: {other:?}"),
}

Type guard

fn is_capsule_metadata(r: &KernelResponse) -> bool {
    matches!(r, KernelResponse::CapsuleMetadata(_))
}

Try / catch

match request_metadata(&mut client).await {
    Ok(entries) => Ok(entries),
    Err(e) if e.to_string().contains("unexpected capsule metadata response") => {
        eprintln!("kernel/CLI version mismatch: {e}");
        Err(e)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: client.request(KernelRequest::GetCapsuleMetadata) resolves to some KernelResponse variant other than CapsuleMetadata or Error.

Common situations: Mismatched CLI and kernel versions where the kernel maps the request to a different response type; a kernel bug returning a generic/empty response for this request; middleware or proxy altering the response.

Related errors


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