astrid-runtime/astrid · error

FUSE provider control path is not canonical

Error message

FUSE provider control path is not canonical

What it means

The registry record's control_path must equal registry::control_path(&mount_id), the canonical derived path for that mount id. If the stored path differs, the record was created by a non-canonical writer, moved between systems, or hand-edited, and the provider refuses to trust it rather than talking to an arbitrary socket path.

Source

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

async fn require_live_lease(
    client: &mut AdminClient,
    acting_principal: &astrid_core::PrincipalId,
    record: &registry::MountRecord,
) -> Result<LeaseStatus> {
    if &record.requested_by != acting_principal {
        bail!("mount was issued to another acting principal");
    }
    kernel_lease_status(client, &record.mount_id)
        .await?
        .with_context(|| format!("storage mount lease {} is stale", record.mount_id))
}

fn validate_record(record: &registry::MountRecord, status: &LeaseStatus) -> Result<()> {
    if status.mountpoint != record.mountpoint || status.access != record.access {
        bail!("kernel lease metadata does not match the FUSE provider registry");
    }
    if record.control_path != registry::control_path(&record.mount_id)? {
        bail!("FUSE provider control path is not canonical");
    }
    Ok(())
}

async fn ensure_mountpoint_available(
    client: &mut AdminClient,
    acting_principal: &astrid_core::PrincipalId,
    mountpoint: &Path,
) -> Result<()> {
    let key = mountpoint
        .to_str()
        .context("mountpoint must be canonical Unicode text")?
        .to_owned();
    let registry: BTreeMap<String, registry::MountRecord> = registry::load_registry()?;
    let Some(record) = registry.get(&key).cloned() else {
        return Ok(());
    };
    let status = kernel_lease_status(client, &record.mount_id).await?;

View on GitHub (pinned to affd8760f4)

Solutions

  1. Regenerate the registry entry: remove the record and re-mount so control_path is recomputed canonically
  2. If a version change altered the path scheme, clear the old registry and remount all mounts with the new provider
  3. Ensure the registry is not shared across users/hosts; keep it under the per-user runtime directory
  4. Stop hand-editing control_path; always let the provider derive it from mount_id

Example fix

// before
"control_path": "/tmp/my-custom-sock.sock"   // hand-edited
// after: derived canonically from mount_id
"control_path": "/run/user/1000/astrid-fuse/control/<mount-id>.sock"
Defensive patterns

Strategy: validation

Validate before calling

// Verify the record's control path is canonical before trusting it
let expected = registry::control_path(&record.mount_id)?;
if record.control_path != expected {
    return Err(anyhow!("non-canonical control path {} (expected {})", record.control_path.display(), expected.display()));
}

Type guard

fn has_canonical_control_path(record: &MountRecord) -> bool {
    registry::control_path(&record.mount_id).map(|c| c == record.control_path).unwrap_or(false)
}

Try / catch

match validate_record(&record, &status) {
    Err(e) if e.to_string().contains("control path is not canonical") => {
        // record from an old scheme or foreign host: purge and remount
        registry::remove_record(&record.mount_id)?;
        remount_fresh(client, &acting_principal, &record.mountpoint).await?;
    }
    other => other,
}

Prevention

When it happens

Trigger: validate_record finds record.control_path != registry::control_path(record.mount_id) — registry file copied from another machine/user (different base temp dir), an older provider version that used a different path scheme, or manual registry edits.

Common situations: Sharing or migrating the registry file between users/hosts where XDG runtime dirs differ; upgrading the provider after a control-path scheme change; symlinks or relative paths stored instead of canonical absolute paths.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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