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

{} not found

Error message

{} not found

What it means

`find_binary_path` searches the known candidate locations for a clash core binary (mihomo/clash, selected by `CoreType`). If none of the candidates exist on disk it throws `NotFound` with the core's executable name, meaning the required core binary was never downloaded or placed.

Source

Thrown at backend/tauri/src/core/clash/mod.rs:20

use specta::Type;
use tauri_specta::Event;

pub mod api;
pub mod proxies;
pub mod ws;

// TODO: support system path search via a config or flag
// FIXME: move this fn to nyanpasu-utils
/// Search the binary path of the core. See [`binary_candidates`] for the
/// search locations and their priority.
pub fn find_binary_path(
    core_type: &nyanpasu_utils::core::CoreType,
) -> std::io::Result<std::path::PathBuf> {
    binary_candidates(core_type)
        .into_iter()
        .find(|path| path.exists())
        .ok_or_else(|| {
            std::io::Error::new(
                std::io::ErrorKind::NotFound,
                format!("{} not found", core_type.get_executable_name()),
            )
        })
}

/// Candidate core binary paths in priority order: data dir -> install dir.
/// Dev builds additionally register the downloaded `externalBin` sidecars
/// (`<crate>/sidecar/`): unlike `tauri build`, where the bundler copies the
/// sidecars next to the executable stripping the target-triple suffix,
/// `tauri dev` copies nothing, so neither the app's exe dir nor Tauri's own
/// sidecar lookup can find the cores there.
fn binary_candidates(core_type: &nyanpasu_utils::core::CoreType) -> Vec<std::path::PathBuf> {
    let name = core_type.get_executable_name();
    let mut candidates = Vec::new();
    if let Ok(data_dir) = crate::utils::dirs::app_data_dir() {
        candidates.push(data_dir.join(name));
    }

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Run the sidecar preparation step (e.g. `pnpm prepare:check`) to download the core binaries into backend/tauri/sidecar/.
  2. Verify the binary exists at the expected location and the core type matches what was downloaded (mihomo vs clash).
  3. Reinstall/repair the app so bundled sidecars are present.
  4. Check that the install directory is writable and the binary was not quarantined.
Defensive patterns

Strategy: validation

Validate before calling

let present = binary_candidates(&core_type).iter().any(|p| p.exists());
if !present {
    anyhow::bail!("core binary for {:?} missing; run sidecar setup", core_type);
}

Try / catch

match find_binary_path(&core_type) {
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => prompt_core_download()?,
    other => other?,
}

Prevention

When it happens

Trigger: Calling `find_binary_path(CoreType::Mihomo)` (or Clash) when no candidate path returned by `binary_candidates` exists — the sidecar binary is missing, was not bundled, or lives in a non-default install dir.

Common situations: Fresh install where `pnpm prepare:check`/sidecar download was skipped, antivirus quarantined the core binary, upgrading the app without re-downloading cores, or running from a source checkout without sidecar/ populated.

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