astrid-runtime/astrid · error

detached FUSE service access {access:?} does not match lease

Error message

detached FUSE service access {access:?} does not match lease

What it means

This error means a live FUSE service's control status returned `ControlResponse::Status` whose `access` does not match the `record.access` stored for that lease. During sync/validation, the library cross-checks the service's live configuration against the persisted record; a mismatch means the running mount does not correspond to the recorded lease. It is thrown in main.rs:363 after `require_live_lease` and `validate_record` succeed.

Source

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

        ControlResponse::Done => {
            bail!("detached FUSE service returned an incompatible readiness response")
        },
    }
}

async fn sync(
    client: &mut AdminClient,
    acting_principal: &astrid_core::PrincipalId,
    selector: &StorageMountSelectorV1,
) -> Result<StorageProviderSuccessV1> {
    let record = registry::resolve_record(selector)?;
    let status = require_live_lease(client, acting_principal, &record).await?;
    validate_record(&record, &status)?;
    let control = live_control_status(client, acting_principal, &record).await?;
    match control {
        ControlResponse::Status { access } if access == record.access => {},
        ControlResponse::Status { access } => {
            bail!("detached FUSE service access {access:?} does not match lease")
        },
        ControlResponse::Done => bail!("FUSE service returned an incompatible status response"),
        ControlResponse::Failure { code, message } => {
            bail!("FUSE service status failed [{code}]: {message}")
        },
    }
    into_success(
        client
            .request(AdminRequestKind::StorageMountSync {
                mount_id: record.mount_id,
            })
            .await?,
    )?;
    Ok(StorageProviderSuccessV1::Synced {
        mount_id: record.mount_id,
    })
}

View on GitHub (pinned to affd8760f4)

Solutions

  1. Restart the detached service from the current lease record so its access matches.
  2. Update or reconcile the lease record if the service's access is actually the intended one.
  3. Ensure only one service owns the control socket path; kill duplicates and clean artifacts.
  4. Verify both sides use the same crate version so StorageProviderAccessV1 equality is reliable.
Defensive patterns

Strategy: type-guard

Type guard

fn access_matches(control: &ControlResponse, record: &LeaseRecord) -> bool {
    matches!(control, ControlResponse::Status { access } if access == &record.access)
}

Try / catch

match sync(client, principal, record).await {
    Err(e) if e.to_string().contains("does not match lease") => {
        // restart service from current record or reconcile the record
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling the sync/status path where `live_control_status` yields `Status { access }` with access != record.access — different access mode, owner, or lease token than recorded.

Common situations: A service started with older parameters still running while the lease record was updated; manual mutation of records; partial upgrade where service and admin client use different access struct versions; two services sharing one control socket path.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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