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

Couldn't get file name of current executable.

Error message

Couldn't get file name of current executable.

What it means

During `unregister` on Linux, the plugin derives the `.desktop` handler file name from the current executable's file name via `tauri_utils::platform::current_exe()`. If the exe path has no final component (e.g. path is `/`, `..`, or otherwise unusual), `file_name()` returns None and this `NotFound` error is thrown.

Source

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

                &format!("x-scheme-handler/{}", scheme),
            ])
            .status()?;
    }

    Ok(())
}

pub fn unregister(_schemes: &[&str]) -> Result<()> {
    let mut target =
        data_dir().ok_or_else(|| Error::new(ErrorKind::NotFound, "data directory not found."))?;

    target.push("applications");

    target.push(format!(
        "{}-handler.desktop",
        tauri_utils::platform::current_exe()?
            .file_name()
            .ok_or_else(|| Error::new(
                ErrorKind::NotFound,
                "Couldn't get file name of current executable.",
            ))?
            .to_string_lossy()
    ));

    remove_file(&target)?;
    target.pop();

    Ok(())
}

pub fn listen<F: FnMut(String) + Send + 'static>(mut handler: F) -> Result<()> {
    std::thread::spawn(move || {
        let addr = format!(
            "/tmp/{}-deep-link.sock",
            ID.get().expect("listen() called before prepare()")
        );

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Ensure the app is launched from a normal file path (not a root-like or dotted path).
  2. Verify the executable still exists on disk after upgrades before unregistering.
  3. Catch ErrorKind::NotFound from unregister and log it instead of failing the shutdown path.
Defensive patterns

Strategy: try-catch

Validate before calling

let exe = std::env::current_exe()?;
if exe.file_name().is_none() {
    log::warn!("current exe path has no file name; skip unregister");
}

Try / catch

if let Err(e) = unregister(&["myapp"]) {
    if e.kind() == std::io::ErrorKind::NotFound { log::warn!("skip: {e}"); } else { return Err(e.into()); }
}

Prevention

When it happens

Trigger: Calling `unregister` when `std::env::current_exe()` resolves to a path whose `file_name()` is None — a path ending in `..`, a deleted/replaced executable, or exotic mount setups where the exe path is a bare root.

Common situations: App launched through a symlink chain that got replaced, running from a path like `/proc/self/exe`-style tricks in sandboxes (Flatpak/firejail), or the binary being deleted while running (upgrades), causing resolution oddities.

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