astrid-runtime/astrid · error

registered FUSE service returned an incompatible status resp

Error message

registered FUSE service returned an incompatible status response

What it means

During mount, the FUSE control channel is expected to answer a status probe with a ControlResponse::Status. If the service replies with some other ControlResponse variant (Done, Failure, etc.), the code cannot determine mount state and bails with this message in crates/astrid-storage-provider-fuse/src/main.rs:825.

Source

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

    let status = kernel_lease_status(client, &record.mount_id).await?;
    let Some(status) = status else {
        cleanup_stale_record(client, acting_principal, &record).await?;
        return Ok(());
    };
    validate_record(&record, &status)?;
    match call_control(
        &record.control_path,
        &ControlRequest::Status {
            requested_by: record.requested_by.clone(),
        },
    ) {
        Ok(ControlResponse::Status { access }) if access == status.access => {
            bail!("mountpoint is already mounted: {}", mountpoint.display())
        },
        Ok(ControlResponse::Status { access }) => {
            bail!("registered FUSE service access {access:?} does not match its lease")
        },
        Ok(_) => bail!("registered FUSE service returned an incompatible status response"),
        Err(_) => {
            cleanup_stale_record(client, acting_principal, &record).await?;
            Ok(())
        },
    }
}

async fn cleanup_stale_record(
    client: &mut AdminClient,
    acting_principal: &astrid_core::PrincipalId,
    record: &registry::MountRecord,
) -> Result<()> {
    let lease_is_live = kernel_lease_status(client, &record.mount_id)
        .await?
        .is_some();
    let _ = call_control(
        &record.control_path,
        &ControlRequest::Unmount {

View on GitHub (pinned to affd8760f4)

Solutions

  1. Ensure the process on the control socket is the matching-version astrid FUSE service; kill or upgrade it if not
  2. Remove stale socket files left by previous runs and retry the mount
  3. Align client and service versions so ControlResponse semantics match

Example fix

// before: probing an unknown process on the socket
let status = query_status(socket)?; // bails on non-Status reply
// after
ensure_fuse_service_running(socket)?; // verify the right service owns the socket
let status = query_status(socket)?;
Defensive patterns

Strategy: type-guard

Validate before calling

let ok = matches!(resp, ControlResponse::Status { .. });

Type guard

fn as_status(resp: &ControlResponse) -> Option<&Access> { match resp { ControlResponse::Status { access } => Some(access), _ => None } }

Try / catch

match result { Err(e) if e.to_string().contains("incompatible status response") => restart_fuse_service()?, r => r? }

Prevention

When it happens

Trigger: Sending a status query over the FUSE control socket and receiving a non-Status response — typically because the listening process is not the expected FUSE control service or speaks a different protocol version.

Common situations: Protocol/version mismatch between the mount client and a running FUSE service; another program occupies the control socket path; an older service binary that lacks the Status response.

Related errors


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