libnyanpasu/clash-nyanpasu · error · std::io::Error (NotFound)

Couldn't get file name of curent executable.

Error message

Couldn't get file name of curent executable.

What it means

The Linux deep-link register() names the generated .desktop file after the current executable (`<name>-handler.desktop`). It calls current_exe().file_name(); when the executable path has no final component (root of a filesystem, deleted path, or exotic exec setup), it fails with this NotFound io::Error.

Source

Thrown at backend/tauri-plugin-deep-link/src/linux.rs:26

use dirs::data_dir;

use crate::ID;

pub fn register<F: FnMut(String) + Send + 'static>(schemes: &[&str], handler: F) -> Result<()> {
    listen(handler)?;

    let mut target = data_dir()
        .ok_or_else(|| Error::new(ErrorKind::NotFound, "data directory not found."))?
        .join("applications");

    create_dir_all(&target)?;

    let exe = tauri_utils::platform::current_exe()?;

    let file_name = format!(
        "{}-handler.desktop",
        exe.file_name()
            .ok_or_else(|| Error::new(
                ErrorKind::NotFound,
                "Couldn't get file name of curent executable.",
            ))?
            .to_string_lossy()
    );

    target.push(&file_name);

    let mime_types = format!(
        "{};",
        schemes
            .iter()
            .map(|s| format!("x-scheme-handler/{}", s))
            .collect::<Vec<String>>()
            .join(";")
    );

    let mut file = File::create(&target)?;

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Ensure the app is launched from a normal on-disk executable path with a file name
  2. Check the inner path: log tauri_utils::platform::current_exe() to see what path was resolved
  3. Avoid running the binary from paths like "/" or from unlinked temp files
  4. If the exotic launch mode is intentional, generate a stable .desktop name from a constant (e.g. the app identifier) instead of exe.file_name()

Example fix

// before
exe.file_name().ok_or_else(|| Error::new(ErrorKind::NotFound, "Couldn't get file name of curent executable."))?
// after
let name = exe.file_name().map(|n| n.to_string_lossy().into_owned())
    .unwrap_or_else(|| "nyanpasu".to_string());
let file_name = format!("{name}-handler.desktop");
Defensive patterns

Strategy: validation

Validate before calling

// before register()
let exe = tauri_utils::platform::current_exe()?;
if exe.file_name().is_none() {
    anyhow::bail!("current exe path {:?} has no file name; cannot build .desktop name", exe);
}

Type guard

fn exe_has_file_name(path: &std::path::Path) -> bool {
    path.file_name().is_some()
}

Try / catch

match deep_link::register(&schemes, handler) {
    Err(e) if e.to_string().contains("file name of curent executable") => {
    log::error!("exe path unusable for .desktop naming: {e}");
    }
    Err(e) => return Err(e.into()),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: register() invoked when std::env::current_exe() / tauri's current_exe returns a path whose file_name() is None — e.g. the binary path is "/", the path was unlinked after exec, or running via unusual mount setups.

Common situations: Container or chroot layouts where /proc/self/exe resolves oddly; app executed from a deleted temp directory; memory-fd execution; symlinks pointing to filesystem root after misconfiguration.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/fbd26480dd8576c2. Report an issue: GitHub.