tauri-apps/tauri · error · anyhow::Error
{:?} is not a file
Error message
{:?} is not a file What it means
The sibling check in tauri-build's copy_file: the source path exists but is not a regular file (typically a directory), while the copy routines here need a concrete file. The Debug-formatted path in the message identifies the entry that resolved to a directory.
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 2f1cd75b0f)
Solutions
- Point the config entry at a concrete file path instead of its containing directory
- For macOS frameworks use a .framework path (copied as a directory by design) or a bare name resolved from standard locations - not an arbitrary directory
- If multiple assets are intended, use the bundle.resources glob/map forms the config supports rather than one directory path
Example fix
// before "externalBin": ["binaries/"] // after "externalBin": ["binaries/mytool-x86_64-unknown-linux-gnu"]
Defensive patterns
Strategy: validation
Validate before calling
// prebuild check: every externalBin entry must be a regular file
const { statSync } = require('fs')
const cfg = JSON.parse(readFileSync('src-tauri/tauri.conf.json', 'utf8'))
for (const b of cfg.bundle?.externalBin ?? []) {
const s = statSync(`src-tauri/${b}`, { throwIfNoEntry: false })
if (s && !s.isFile()) throw new Error(`externalBin entry is not a file: ${b}`)
} Prevention
- Point externalBin at concrete files with the target-triple suffix, never at directories
- For directories of assets use bundle.resources globs/maps instead
- Add a prebuild lint that stat()s every configured binary path
When it happens
Trigger: A bundle.externalBin entry or a .dylib framework entry (anything funneled through copy_file) resolving to a directory - e.g. pointing externalBin at the folder containing sidecar binaries, or listing an assets directory where a single file is required.
Common situations: Confusing a directory of assets or binaries with one file in tauri.conf.json; glob/map expansion producing the parent directory; naming a macOS framework bundle directory where a .dylib file path is expected.
Related errors
- {:?} does not exist
- Permission {} not found, expected one of {}
- Cannot define a sidecar with the same name as the Cargo pack
- Library not found: {}
- Framework path should have .framework extension: {}
AI-assisted analysis of tauri-apps/tauri@2f1cd75b0f (2026-08-16).
Data as JSON: /api/errors/f6e037c8d5fb6a90.
Report an issue: GitHub.