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: ®istry::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: ®istry::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
- Regenerate the registry entry: remove the record and re-mount so control_path is recomputed canonically
- If a version change altered the path scheme, clear the old registry and remount all mounts with the new provider
- Ensure the registry is not shared across users/hosts; keep it under the per-user runtime directory
- 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
- Always derive control_path via registry::control_path(mount_id); never store ad-hoc paths
- Do not copy the registry file between users or hosts — runtime dirs differ per machine/user
- After a control-path scheme change in the provider, clear the registry and remount everything
- Store absolute canonical paths only (no symlinks or relative segments)
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
- Astrid volume is not a regular file
- capsule source is neither a directory nor a regular file: {}
- durable capsule {id} metadata names a hash for a non-WASM co
- empty archive path
- unsafe archive path '{path}'
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/5ee13444a55b1a44.
Report an issue: GitHub.