astrid-runtime/astrid · error

FSKit service mountpoint overlaps the lease resource

Error message

FSKit service mountpoint overlaps the lease resource

What it means

During FSKit service launch validation, the provider rejects a launch whose mountpoint path overlaps (equals, nests under, or contains) the lease resource_path. The lease resource directory is a private kernel-managed area; mounting a filesystem on top of it (or vice versa) would shadow or corrupt the lease data. This is a deliberate safety check in validate_launch.

Source

Thrown at crates/astrid-storage-provider-fskit/src/service.rs:134

        .context("read FSKit service launch")?;
    if bytes.len() as u64 > MAX_LAUNCH_BYTES {
        bail!("FSKit service launch exceeds limit");
    }
    serde_json::from_slice(&bytes).context("decode FSKit service launch")
}

fn validate_launch(launch: &StorageProviderServiceLaunchV1) -> Result<()> {
    if launch.schema != STORAGE_FILESYSTEM_SERVICE_LAUNCH_SCHEMA_V1 {
        bail!("unsupported FSKit service launch schema {}", launch.schema);
    }
    validate_launch_parent(&launch.parent)?;
    validate_lease(&launch.lease)?;
    crate::validate_mountpoint_layout(&launch.mountpoint)?;
    if launch.mountpoint == launch.lease.resource_path
        || launch.mountpoint.starts_with(&launch.lease.resource_path)
        || launch.lease.resource_path.starts_with(&launch.mountpoint)
    {
        bail!("FSKit service mountpoint overlaps the lease resource");
    }
    crate::validate_mountpoint_ancestors(&launch.mountpoint)?;
    crate::validate_unmounted_mountpoint(&launch.mountpoint)?;
    validate_control_path(&launch.control_path, &launch.lease.resource_path)?;
    Ok(())
}

fn validate_lease(lease: &astrid_core::storage_filesystem::StorageMountLeaseV1) -> Result<()> {
    if lease.lease_token.len() < 16 || lease.lease_token.len() > 4096 {
        bail!("FSKit lease callback token is invalid");
    }
    let now = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .context("read system clock")?
        .as_secs();
    if lease.expires_at_epoch_secs < now {
        bail!("FSKit lease is expired");
    }

View on GitHub (pinned to affd8760f4)

Solutions

  1. Choose a mountpoint that is a disjoint path from the lease resource_path (no prefix relationship in either direction)
  2. Regenerate the launch config so mountpoint lives outside the lease resource directory
  3. If the intent is to mount the leased filesystem itself, use the provider's managed mount flow instead of supplying an overlapping mountpoint manually

Example fix

// before
launch.mountpoint = PathBuf::from("/var/fskit/leases/abc/resource");
// after
launch.mountpoint = PathBuf::from("/mnt/fskit/abc");
Defensive patterns

Strategy: validation

Validate before calling

fn mountpoint_ok(launch: &StorageMountLaunchV1) -> bool {
    let r = &launch.lease.resource_path;
    launch.mountpoint != *r
        && !launch.mountpoint.starts_with(r)
        && !r.starts_with(&launch.mountpoint)
}

Type guard

fn is_disjoint(child: &Path, parent: &Path) -> bool {
    !(child.starts_with(parent) || parent.starts_with(child))
}

Prevention

When it happens

Trigger: Calling run/validate_launch with a StorageMountLaunchV1 where launch.mountpoint == lease.resource_path, launch.mountpoint is a subpath of lease.resource_path, or lease.resource_path is a subpath of launch.mountpoint.

Common situations: Config generators that reuse the same directory for both the lease resource and the mount target; templated configs that substitute the lease path into the mountpoint field; scripts that assume mountpoint can default to resource_path.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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