astrid-runtime/astrid · error

daemon did not return capsule metadata for WIT GC

Error message

daemon did not return capsule metadata for WIT GC

What it means

query_daemon_marks asks the kernel daemon via KernelRequest::GetCapsuleMetadata for capsule metadata used to collect WIT hashes for garbage collection. The kernel_api enum only treats the CapsuleMetadata variant as valid; any other KernelResponse variant means the daemon misunderstood or mishandled the request, so the code bails with this message.

Solutions

  1. Restart/upgrade the astrid daemon so its kernel_api matches the CLI's expectations and returns CapsuleMetadata
  2. Verify you are connecting to the correct workspace kernel socket (connect_kernel_for_workspace(None) resolution)
  3. Check the daemon logs for the handler of KernelRequest::GetCapsuleMetadata failing and returning an error variant
  4. Make the response handling tolerant by matching explicit error variants with clearer messages before the let-else

Example fix

// before
let astrid_core::kernel_api::KernelResponse::CapsuleMetadata(entries) = response else {
    anyhow::bail!("daemon did not return capsule metadata for WIT GC")
};
// after
match response {
    KernelResponse::CapsuleMetadata(entries) => Ok(entries),
    other => anyhow::bail!("daemon returned {other:?} instead of capsule metadata for WIT GC"),
}
Defensive patterns

Strategy: try-catch

Validate before calling

// after sending GetCapsuleMetadata, check variant before destructuring:
fn is_capsule_metadata(r: &KernelResponse) -> bool { matches!(r, KernelResponse::CapsuleMetadata(_)) }

Type guard

fn as_capsule_metadata(r: KernelResponse) -> Option<Vec<CapsuleMetadataEntry>> { match r { KernelResponse::CapsuleMetadata(e) => Some(e), _ => None } }

Try / catch

let marks = async { ... }.await.map_err(|e| {
    eprintln!("WIT GC: daemon metadata query failed: {e}; skipping GC marks");
    e
});

Prevention

When it happens

Trigger: client.request(KernelRequest::GetCapsuleMetadata) resolves to a KernelResponse variant other than CapsuleMetadata (e.g. an error/ack variant), triggering the let-else bail at wit.rs:166 inside query_daemon_marks, called from collect_marks.

Common situations: Daemon running an older/other protocol version that responds with a legacy or error variant; connected to the wrong socket so a different kernel build answers; daemon-side handler for GetCapsuleMetadata not implemented and returns a generic fallback response; transient daemon restart returning an error envelope.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at crates/astrid-cli/src/commands/wit.rs:166

) -> anyhow::Result<HashSet<String>> {
    let mut marks = query_daemon_marks()?;
    let workspace_root = std::env::current_dir().ok();
    marks.extend(collect_marks_in_workspace(
        home,
        workspace_root.as_deref(),
        workspace_layout,
    )?);
    Ok(marks)
}

fn query_daemon_marks() -> anyhow::Result<HashSet<String>> {
    let request = async {
        let mut client = crate::socket_client::connect_kernel_for_workspace(None).await?;
        let response = client
            .request(astrid_core::kernel_api::KernelRequest::GetCapsuleMetadata)
            .await?;
        let astrid_core::kernel_api::KernelResponse::CapsuleMetadata(entries) = response else {
            anyhow::bail!("daemon did not return capsule metadata for WIT GC")
        };
        Ok(entries
            .into_iter()
            .flat_map(|entry| entry.wit_hashes)
            .collect())
    };
    if let Ok(handle) = tokio::runtime::Handle::try_current() {
        tokio::task::block_in_place(|| handle.block_on(request))
    } else {
        let runtime = tokio::runtime::Builder::new_current_thread()
            .enable_all()
            .build()
            .context("build runtime for daemon WIT metadata")?;
        runtime.block_on(request)
    }
}

fn collect_marks_in_workspace(

View on GitHub (pinned to affd8760f4)