astrid-runtime/astrid · error

WinFsp mountpoint is not valid UTF-16

Error message

WinFsp mountpoint is not valid UTF-16

What it means

Raised in `run_private_service` (crates/astrid-storage-provider-winfsp/src/win.rs:210) when `U16CString::from_os_str` fails to convert the configured mountpoint path into a NUL-terminated UTF-16 string, which WinFsp requires. The error is thrown before `FileSystem::start` is invoked. It means the mountpoint `Path` contains characters that cannot be represented as UTF-16 (interior NUL bytes on Windows paths), so a valid Windows mountpoint string could not be built.

Source

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

    launch: StorageProviderServiceLaunchV1,
    challenge: String,
    runtime: Arc<tokio::runtime::Runtime>,
) -> Result<()> {
    if !parent_is_alive(&launch.parent) {
        bail!("WinFsp service parent process is not alive");
    }
    probe_callback(&launch).await?;
    let listener = local_transport::bind(&launch.control_path).with_context(|| {
        format!(
            "bind WinFsp service control {}",
            launch.control_path.display()
        )
    })?;
    let callback = CallbackFs::new(launch.lease.clone(), runtime)
        .map_err(|failure| anyhow::anyhow!("build WinFsp callback filesystem: {failure:?}"))?;
    initialize_winfsp()?;
    let mountpoint = U16CString::from_os_str(launch.mountpoint.as_os_str())
        .map_err(|_| anyhow::anyhow!("WinFsp mountpoint is not valid UTF-16"))?;
    let filesystem = FileSystem::start(
        volume_params(launch.lease.access),
        Some(&mountpoint),
        callback,
    )
    .map_err(|status| anyhow::anyhow!("WinFsp failed to start private mount: {status:#x}"))?;
    let ready = StorageProviderServiceReadyV1 {
        schema: STORAGE_FILESYSTEM_SERVICE_READY_SCHEMA_V1,
        provider: crate::PROVIDER_NAME.to_owned(),
        mount_id: launch.lease.mount_id.as_uuid(),
        control_path: launch.control_path.clone(),
        challenge,
    };
    let mut stdout = std::io::stdout().lock();
    serde_json::to_writer(&mut stdout, &ready).context("encode WinFsp readiness")?;
    stdout
        .write_all(b"\n")
        .context("terminate WinFsp readiness response")?;

View on GitHub (pinned to affd8760f4)

Solutions

  1. Check the mountpoint value passed to the WinFsp launch for embedded NUL bytes and remove them.
  2. Validate the mountpoint path in the daemon/config layer before spawning the WinFsp service (e.g. reject paths whose OsStr encoding contains NUL).
  3. Use a conventional mountpoint such as a drive designator (`X:`) or a normal directory path and retry.
  4. Re-encode the path from its original text source rather than from raw bytes.

Example fix

// before
let mountpoint = U16CString::from_os_str(launch.mountpoint.as_os_str())
    .map_err(|_| anyhow::anyhow!("WinFsp mountpoint is not valid UTF-16"))?;
// after (validate earlier)
if launch.mountpoint.as_os_str().to_str().map_or(true, |s| s.contains('\0')) {
    bail!("mountpoint contains NUL bytes: {:?}", launch.mountpoint);
}
let mountpoint = U16CString::from_os_str(launch.mountpoint.as_os_str())?;
Defensive patterns

Strategy: validation

Validate before calling

fn mountpoint_is_utf16_safe(p: &Path) -> bool {
    p.as_os_str().to_str().map_or(false, |s| !s.contains('\0'))
}
assert!(mountpoint_is_utf16_safe(&PathBuf::from("Q:\\")));

Type guard

fn valid_mountpoint(p: &std::path::Path) -> Option<&str> {
    p.to_str().filter(|s| !s.contains('\0'))
}

Try / catch

let mountpoint = U16CString::from_os_str(launch.mountpoint.as_os_str())
    .map_err(|_| anyhow::anyhow!(
        "WinFsp mountpoint {:?} is not valid UTF-16 (contains NUL?)",
        launch.mountpoint
    ))?;

Prevention

When it happens

Trigger: Specifically: `U16CString::from_os_str(launch.mountpoint.as_os_str())` returns `Err`, i.e. `launch.mountpoint` contains an interior NUL byte or is otherwise not convertible to a UTF-16 C string. All normal Windows paths convert fine; only paths with embedded NULs fail.

Common situations: A mountpoint was built programmatically from raw bytes that include a NUL; a corrupted config file or IPC payload produced a mangled path; a caller passed a path constructed with `CString`-style data instead of normal OS path text.

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