libnyanpasu/clash-nyanpasu · error

failed to get core dir

Error message

failed to get core dir

What it means

During a core update, replace_core locates the directory of the running executable via current_exe() and takes its parent as the core install directory. If current_exe() returns a root-level path with no parent directory, the error is thrown and the core binary cannot be replaced in place.

Source

Thrown at backend/tauri/src/core/updater/instance.rs:230

        tracing::debug!("writing core to {:?} ({} bytes)", tmp_core, buff.len());
        let mut core_file = tokio::fs::File::create(&tmp_core).await?;
        tokio::io::copy(&mut buff.as_slice(), &mut core_file).await?;
        #[cfg(target_family = "unix")]
        {
            std::fs::set_permissions(&tmp_core, std::fs::Permissions::from_mode(0o755))?;
        }
        Ok(())
    }

    async fn replace_core(&self) -> anyhow::Result<()> {
        self.dispatch_state(UpdaterState::Replacing);

        #[cfg(target_os = "windows")]
        let target_core = format!("{}.exe", self.core_type);
        #[cfg(not(target_os = "windows"))]
        let target_core = self.core_type.clone().to_string();
        let core_dir = tauri::utils::platform::current_exe()?;
        let core_dir = core_dir.parent().ok_or(anyhow!("failed to get core dir"))?;
        let target_core = core_dir.join(target_core);
        let tmp_core_path = self.temp_dir.path().join(format!(
            "{}{}",
            self.core_type,
            std::env::consts::EXE_SUFFIX
        ));

        self.nyanpasu
            .replace_core_binary(crate::client::core_lifecycle::ports::PreparedCoreBinary {
                target: self.core_type,
                source: tmp_core_path,
                destination: target_core,
                staging: self.temp_dir.clone(),
                progress: Arc::new(UpdaterInstallProgress(self.inner.clone())),
            })
            .await?;

        Ok(())

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Install/run the app from a normal subdirectory, not a filesystem root
  2. Log current_exe() output to confirm the resolved path before replacement
  3. Fall back to a configured install directory instead of deriving it from current_exe

Example fix

// before
let core_dir = core_dir.parent().ok_or(anyhow!("failed to get core dir"))?;
// after
let core_dir = core_dir.parent().with_context(|| format!("current exe has no parent dir: {:?}", core_dir))?;
Defensive patterns

Strategy: validation

Validate before calling

let exe = tauri::utils::platform::current_exe()?;
if exe.parent().is_none() {
    eprintln!("cannot determine core dir: exe {:?} has no parent", exe);
}

Type guard

fn exe_parent_dir() -> Option<std::path::PathBuf> {
    tauri::utils::platform::current_exe().ok()?.parent().map(|p| p.to_path_buf())
}

Try / catch

match replace_core(/* ... */).await {
    Ok(n) => n,
    Err(e) if e.to_string().contains("failed to get core dir") => /* abort update, report unusable install location */,
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling start -> replace_core when the app executable sits at a filesystem root (e.g. '/nyanpasu' where parent exists but root '/' where it doesn't, or deleted cwd scenarios) so core_dir.parent() returns None.

Common situations: Running the binary from a drive root on Windows (C:\nyanpasu.exe -> parent C:\ exists, but exotic sandbox/mount setups can yield parentless paths), containerized or chroot environments, or a deleted/renamed install directory.

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