astrid-runtime/astrid · error

kernel returned an unexpected storage mount response

Error message

kernel returned an unexpected storage mount response

What it means

lease_from_response expects the kernel to answer a mount-lease request with AdminResponseBody::StorageMountLease or AdminResponseBody::Error. Any other AdminResponseBody variant (e.g. Success) is unexpected, so it bails with this message (crates/astrid-storage-provider-fuse/src/main.rs:898).

Source

Thrown at crates/astrid-storage-provider-fuse/src/main.rs:898

    }
}

fn cleanup_mountpoint(mountpoint: &Path, auto_created: bool) -> Result<()> {
    if auto_created
        && !mountpoint::mountinfo_contains(mountpoint)?
        && std::fs::symlink_metadata(mountpoint).is_ok_and(|metadata| metadata.is_dir())
        && std::fs::read_dir(mountpoint)?.next().is_none()
    {
        let _ = std::fs::remove_dir(mountpoint);
    }
    Ok(())
}

fn lease_from_response(body: AdminResponseBody) -> Result<StorageMountLeaseV1> {
    match body {
        AdminResponseBody::StorageMountLease(lease) => Ok(*lease),
        AdminResponseBody::Error(error) => bail!("kernel refused storage mount: {error}"),
        _ => bail!("kernel returned an unexpected storage mount response"),
    }
}

fn into_success(body: AdminResponseBody) -> Result<serde_json::Value> {
    match body {
        AdminResponseBody::Success(value) => Ok(value),
        AdminResponseBody::Error(error) => {
            bail!("kernel refused storage lifecycle request: {error}")
        },
        _ => bail!("kernel returned an unexpected storage lifecycle response"),
    }
}

#[cfg(test)]
mod launcher_tests {
    use super::{
        ControlResponse, StorageProviderAccessV1, require_ready_control_response,
        require_service_running_after_handoff,

View on GitHub (pinned to affd8760f4)

Solutions

  1. Upgrade the FUSE provider and kernel to matching versions so AdminResponseBody variants align
  2. Confirm the request targets the storage-mount-lease endpoint and not a generic action endpoint
  3. Capture the raw response body in logs and verify its variant before parsing

Example fix

// before
let lease = lease_from_response(send(request).body)?; // unexpected variant
// after
let body = send(request).body;
assert_matches!(body, AdminResponseBody::StorageMountLease(_) | AdminResponseBody::Error(_));
let lease = lease_from_response(body)?;
Defensive patterns

Strategy: type-guard

Validate before calling

let ok = matches!(body, AdminResponseBody::StorageMountLease(_) | AdminResponseBody::Error(_));

Type guard

fn is_lease_body(body: &AdminResponseBody) -> bool { matches!(body, AdminResponseBody::StorageMountLease(_) | AdminResponseBody::Error(_)) }

Try / catch

match lease_from_response(body) { Err(e) if e.to_string().contains("unexpected storage mount response") => upgrade_client_to_match_kernel()?, r => r? }

Prevention

When it happens

Trigger: Sending a mount-lease request and getting a response body of the wrong variant — typically a client/server version mismatch or the request being routed to an endpoint that returns a generic Success.

Common situations: Version skew between the FUSE provider and the kernel admin API; a proxy or misconfiguration routing the lease request to the wrong endpoint; request/response shape changed after an upgrade.

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