astrid-runtime/astrid · error

WinFsp daemon lease contains a relative endpoint

Error message

WinFsp daemon lease contains a relative endpoint

What it means

After decoding the daemon start document, daemon_main validates that the mountpoint is either absolute or a drive designator (e.g. 'X:'), and that lease.callback_path is absolute. If either is relative, the daemon bails because relative paths in a spawned daemon would resolve against an unpredictable working directory.

Source

Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:65

}

pub(crate) fn daemon_main() -> Result<()> {
    let mut bytes = Vec::new();
    std::io::stdin()
        .lock()
        .take(MAX_LEASE_BYTES + 1)
        .read_to_end(&mut bytes)
        .context("read WinFsp daemon lease")?;
    if bytes.len() as u64 > MAX_LEASE_BYTES {
        bail!("WinFsp daemon lease exceeds limit");
    }
    let start: DaemonStart =
        serde_json::from_slice(&bytes).context("decode WinFsp daemon lease")?;
    let lease = start.lease;
    if (!start.mountpoint.is_absolute() && !is_drive_designator(&start.mountpoint))
        || !lease.callback_path.is_absolute()
    {
        bail!("WinFsp daemon lease contains a relative endpoint");
    }

    let runtime = Arc::new(
        tokio::runtime::Builder::new_multi_thread()
            .enable_all()
            .build()
            .context("start WinFsp callback runtime")?,
    );
    let callback = CallbackFs::new(lease.clone(), Arc::clone(&runtime))
        .map_err(|failure| anyhow::anyhow!("build WinFsp callback filesystem: {failure:?}"))?;
    let control_path = provider_control_path(&lease.mount_id)?;
    let control_listener = local_transport::bind(&control_path)
        .with_context(|| format!("bind WinFsp control endpoint {}", control_path.display()))?;
    initialize_winfsp()?;
    let mountpoint = U16CString::from_os_str(start.mountpoint.as_os_str())
        .map_err(|_| anyhow::anyhow!("mountpoint is not valid UTF-16"))?;
    let filesystem = FileSystem::start(volume_params(lease.access), Some(&mountpoint), callback)
        .map_err(|status| {

View on GitHub (pinned to affd8760f4)

Solutions

  1. Pass an absolute mountpoint path or a drive designator like 'X:' (a drive letter with colon is accepted)
  2. Absolutize callback_path before writing the lease (std::fs::canonicalize or joining with a known base dir)
  3. In the launcher, reject/normalize relative paths at config parse time with context about the CWD used

Example fix

// before
DaemonStart { mountpoint: PathBuf::from("mounts/astrid"), .. }
// after
DaemonStart { mountpoint: PathBuf::from("C:\\mounts\\astrid"), .. } // or canonicalize() the input
Defensive patterns

Strategy: validation

Validate before calling

if !mountpoint.is_absolute() && !is_drive_designator(&mountpoint) {
    return Err(format!("mountpoint must be absolute or a drive designator: {}", mountpoint.display()));
}
if !callback_path.is_absolute() {
    return Err(format!("callback_path must be absolute: {}", callback_path.display()));
}

Type guard

fn is_absolute_or_drive(p: &Path) -> bool {
    p.is_absolute() || p.to_str().map(is_drive_designator).unwrap_or(false)
}

Try / catch

match daemon_err {
    Err(e) if e.to_string().contains("relative endpoint") => {
        eprintln!("absolutize mountpoint/callback_path before launch");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Launching the WinFsp daemon with a relative mountpoint string that is not a drive designator (e.g. 'mounts/astrid'), or a lease whose callback_path was built without absolutization (e.g. from a relative CLI flag or config value).

Common situations: Passing a relative path from a config file or --mount flag; a Windows service or scheduled task starting the daemon with a different CWD than the parent assumed; constructing callback_path with std::env::current_dir() skipped.

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/afacb1e2c05093c2. Report an issue: GitHub.