tauri-apps/tauri · error
is not a file
Error message
{:?} is not a file What it means
copy_file in tauri-build rejects sources that exist but are not regular files (e.g. directories, symlinks to dirs, or special files), because fs::copy only works on files. The offending path is embedded in the message.
Solutions
- Change the config entry to point to a concrete file, or use a glob pattern (e.g. `dir/**`) to include directory contents
- Replace symlink-to-directory sources with the real file path or copy semantics
- Verify with `ls -la` / `Get-Item` that the path is a regular file
Example fix
// before (tauri.conf.json) "resources": ["assets/configs"] // is a directory // after "resources": ["assets/configs/**"]
Defensive patterns
Strategy: validation
Validate before calling
const isRegularFile = (p: string) => { try { return fs.statSync(p).isFile(); } catch { return false; } };
for (const r of cfg.bundle?.resources ?? []) {
const p = resolve('src-tauri', r.replace(/[*].*$/, ''));
if (fs.existsSync(p) && !isRegularFile(p) && !r.includes('*')) throw new Error(`Use a glob for directories: ${r}`);
} Type guard
const isFile = (p: string): p is string => fs.statSync(p, { throwIfNoEntry: false })?.isFile() === true; Try / catch
try {
await copy(from, to);
} catch (e) {
if (String(e).includes('is not a file')) throw new Error(`Point resources at files or use ** globs: ${e.message}`);
throw e;
} Prevention
- Never point `resources` directly at a directory entry; use `dir/**`
- Check symlinks resolve to regular files on the build machine
- Lint tauri.conf.json paths in CI before building
When it happens
Trigger: A `bundle.resources` or frameworks entry in tauri.conf.json resolves to a directory or non-regular file when copy_file is called from copy_binaries/copy_resources/copy_frameworks.
Common situations: Pointing `resources` directly at a directory instead of using a glob or directory-copy semantics, a symlink to a directory, or a config path that accidentally matches a folder.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- does not exist
- Cannot define a sidecar with the same name as the Cargo…
- Failed to canonicalize `WRY_ANDROID_KOTLIN_FILES_OUT_DIR`…
- failed to read plugin global API script
- ' ' is not a directory.
AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18).
Data as JSON: /api/errors/f6e037c8d5fb6a90.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tauri-build/src/lib.rs:50
mod codegen;
mod manifest;
mod mobile;
mod static_vcruntime;
#[cfg(feature = "codegen")]
#[cfg_attr(docsrs, doc(cfg(feature = "codegen")))]
pub use codegen::context::CodegenContext;
pub use acl::{AppManifest, DefaultPermissionRule, InlinedPlugin};
fn copy_file(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<()> {
let from = from.as_ref();
let to = to.as_ref();
if !from.exists() {
return Err(anyhow::anyhow!("{:?} does not exist", from));
}
if !from.is_file() {
return Err(anyhow::anyhow!("{:?} is not a file", from));
}
let dest_dir = to.parent().expect("No data in parent");
fs::create_dir_all(dest_dir)?;
fs::copy(from, to)?;
Ok(())
}
fn copy_binaries(
binaries: ResourcePaths,
target_triple: &str,
path: &Path,
package_name: Option<&str>,
) -> Result<()> {
for src in binaries {
let src = src?;
println!("cargo:rerun-if-changed={}", src.display());
let file_name = src
.file_name()View on GitHub (pinned to 460ec35447)