astrid-runtime/astrid · error

FUSE callback path is not the kernel lease endpoint

Error message

FUSE callback path is not the kernel lease endpoint

What it means

The callback path must be exactly `<resource_path>/control.sock` — the fixed endpoint the kernel/parent expects for lease control traffic. A callback path pointing anywhere else is rejected so the helper and parent always agree on the control socket location.

Solutions

  1. Derive `callback_path` as `resource_path.join("control.sock")` instead of setting it independently.
  2. Regenerate the lease with the standard broker so both paths are consistent.
  3. Fix lease.json (or lease-construction code) so callback_path matches the required endpoint.
  4. If you need a different socket location, change the resource_path — the callback follows it.

Example fix

// before
callback_path: PathBuf::from("/run/astrid/fuse.sock"),
// after
callback_path: resource_path.join("control.sock"),
Defensive patterns

Strategy: validation

Validate before calling

fn callback_matches(lease: &StorageMountLeaseV1) -> bool {
    lease.callback_path == lease.resource_path.join("control.sock")
}
if !callback_matches(&lease) { return Err("callback path mismatch"); }

Type guard

fn has_kernel_lease_endpoint(lease: &StorageMountLeaseV1) -> bool {
    lease.callback_path == lease.resource_path.join("control.sock")
}

Prevention

When it happens

Trigger: `validate_lease` compares `lease.callback_path != lease.resource_path.join("control.sock")` and bails when they differ during `validate_launch`.

Common situations: Hand-written lease.json with a custom socket name; two mounts configured with colliding paths moved the callback elsewhere; a refactor renamed the socket on one side only; copied lease config from another mount with a different resource path.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at crates/astrid-storage-provider-fuse/src/service.rs:222

fn validate_lease(lease: &StorageMountLeaseV1) -> Result<()> {
    if lease.lease_token.len() < 16
        || lease.lease_token.len() > 4096
        || lease.lease_token.chars().any(char::is_control)
    {
        bail!("invalid FUSE callback token");
    }
    let now = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .context("read system clock")?
        .as_secs();
    if lease.expires_at_epoch_secs < now {
        bail!("FUSE lease is expired");
    }
    if !lease.resource_path.is_absolute() || !lease.callback_path.is_absolute() {
        bail!("FUSE lease paths must be absolute");
    }
    if lease.callback_path != lease.resource_path.join("control.sock") {
        bail!("FUSE callback path is not the kernel lease endpoint");
    }
    platform_fs::validate_private_directory(&lease.resource_path)
        .context("validate private FUSE lease resource")?;
    platform_fs::verify_no_redirects(&lease.resource_path)
        .context("reject redirected FUSE lease resource")?;
    let manifest_path = lease.resource_path.join("lease.json");
    platform_fs::validate_private_file(&manifest_path)
        .context("validate private FUSE lease manifest")?;
    let manifest = std::fs::read(&manifest_path).context("read FUSE lease manifest")?;
    if manifest.len() > 64 * 1024 {
        bail!("FUSE lease manifest exceeds the bounded size");
    }
    let admitted: StorageMountLeaseV1 =
        serde_json::from_slice(&manifest).context("decode FUSE lease manifest")?;
    if admitted != *lease {
        bail!("FUSE launch lease does not match the kernel manifest");
    }
    Ok(())

View on GitHub (pinned to affd8760f4)