tauri-apps/tauri · error · std::io::Error
source does not exist
Error message
source does not exist
What it means
tauri-cli's copy_file helper guards every copy by first checking from.exists(); when the source path is missing it returns Error::Fs with context 'failed to copy file', the offending path, and an inner NotFound io::Error ('source does not exist'). The check exists to fail fast with a precise path instead of letting a raw OS error surface later.
Source
Thrown at crates/tauri-cli/src/helpers/fs.rs:18
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use crate::{
error::{Context, ErrorExt},
Error,
};
use std::path::{Path, PathBuf};
pub fn copy_file(from: impl AsRef<Path>, to: impl AsRef<Path>) -> crate::Result<()> {
let from = from.as_ref();
let to = to.as_ref();
if !from.exists() {
Err(Error::Fs {
context: "failed to copy file",
path: from.to_path_buf(),
error: std::io::Error::new(std::io::ErrorKind::NotFound, "source does not exist"),
})?;
}
if !from.is_file() {
Err(Error::Fs {
context: "failed to copy file",
path: from.to_path_buf(),
error: std::io::Error::other("not a file"),
})?;
}
let dest_dir = to.parent().expect("No data in parent");
std::fs::create_dir_all(dest_dir)
.fs_context("failed to create directory", dest_dir.to_path_buf())?;
std::fs::copy(from, to).fs_context("failed to copy file", from.to_path_buf())?;
Ok(())
}
/// Find an entry in a directory matching a glob pattern.
/// Currently does not traverse subdirectories.View on GitHub (pinned to 52e4b6e71d)
Solutions
- Compare the exact `path` field in the error against the filesystem, checking character case on Linux
- Fix the case or spelling in tauri.conf.json / code so it matches the real file
- If the file is generated, make sure the generating step runs and succeeds before the copy
- Re-run `tauri icon` or the codegen command, or restore the deleted file, then rebuild
Example fix
// before (tauri.conf.json): "licenseFile": "./LICENCE" // actual file: LICENSE // after: "licenseFile": "./LICENSE"
Defensive patterns
Strategy: validation
Validate before calling
// Rust callers: verify source before copying
fn safe_copy(from: &std::path::Path, to: &std::path::Path) -> std::io::Result<u64> {
let meta = std::fs::metadata(from)
.map_err(|e| std::io::Error::new(e.kind(), format!("missing source {from:?}: {e}")))?;
if !meta.is_file() {
return Err(std::io::Error::other(format!("{from:?} is not a regular file")));
}
if let Some(dir) = to.parent() { std::fs::create_dir_all(dir)?; }
std::fs::copy(from, to)
} Prevention
- Develop on a case-sensitive filesystem (or run CI on Linux) to catch path-case mismatches early
- Make codegen steps fail loudly so missing artifacts are caught before copies
- After renaming files, grep tauri.conf.json and code for stale paths
When it happens
Trigger: Any tauri-cli/bundler code path that copies a declared file — icons, license files, templates, generated artifacts — where the source was deleted, misnamed, or never created by the step that was supposed to generate it. Note the exists() check is also a TOCTOU race: a file removed between check and copy still yields a raw OS error.
Common situations: Case-sensitivity mismatches that work on macOS/Windows but fail on Linux CI (Icon.png vs icon.png); paths pointing at files removed by cargo clean or excluded via gitignore; a codegen step skipped because an earlier command failed; stale config after a file rename.
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
- File does not exist at path: {path}
- No file found in {} matching {}
- asset protocol path "{path}" is not valid: {e}
- Missing OS permission to access path "{path}": {e}
- Couldn't recognize the {} folder as a Tauri project. It must
AI-assisted analysis of tauri-apps/tauri@52e4b6e71d (2026-08-20).
Data as JSON: /api/errors/90b0a5d4ea91d772.
Report an issue: GitHub.