tauri-apps/tauri · critical

Couldn't get library filename

Error message

Couldn't get library filename

What it means

In tauri-build's copy_frameworks, a `.dylib` entry that exists on disk is copied by joining its `file_name()` to the destination directory. If the dylib path lacks a final component (root, trailing separator, `..`), file_name() returns None and the expect panics. Since existence was already checked, this only happens for structurally malformed paths that nonetheless resolve oddly (or races replaced the path).

Solutions

  1. Ensure the dylib entry in tauri.conf.json ends with the actual file name, e.g. `libs/libfoo.dylib`.
  2. Strip `..` and trailing separators; use a canonical absolute path.
  3. Check that the file (not a directory) exists at that exact path.
  4. Fail fast in your build script: `assert!(p.is_file() && p.file_name().is_some())` before try_build.

Example fix

// before
"frameworks": ["/usr/local/lib/"]
// after
"frameworks": ["/usr/local/lib/libmylib.dylib"]
Defensive patterns

Strategy: validation

Validate before calling

let p = std::path::Path::new("libs/libmylib.dylib");
assert!(p.is_file() && p.file_name().is_some(), "dylib path invalid: {}", p.display());

Type guard

fn valid_dylib(p: &std::path::Path) -> bool {
  p.file_name().is_some() && p.is_file() && p.extension().map_or(false, |e| e == "dylib")
}

Prevention

When it happens

Trigger: tauri_build::try_build with Attributes::copy_frameworks containing a `.dylib` path such as `/path/to/..` or ending in `/` that still passes the `exists()` check but yields no filename.

Common situations: Paths assembled from environment variables where the dylib name was dropped; using a directory that happens to end in `.dylib` is impossible but a symlink or `..`-based path can slip through the exists() check.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18). Data as JSON: /api/errors/6a59080625f08273. Report an issue: GitHub.

Appendix: source

Thrown at crates/tauri-build/src/lib.rs:186

// Copies the macOS application bundle frameworks to the target folder
fn copy_frameworks(dest_dir: &Path, frameworks: &[String]) -> Result<()> {
  fs::create_dir_all(dest_dir)
    .with_context(|| format!("Failed to create frameworks output directory at {dest_dir:?}"))?;
  for framework in frameworks.iter() {
    if framework.ends_with(".framework") {
      let src_path = Path::new(framework);
      let src_name = src_path
        .file_name()
        .expect("Couldn't get framework filename");
      let dest_path = dest_dir.join(src_name);
      copy_dir(src_path, &dest_path)?;
      continue;
    } else if framework.ends_with(".dylib") {
      let src_path = Path::new(framework);
      if !src_path.exists() {
        return Err(anyhow::anyhow!("Library not found: {}", framework));
      }
      let src_name = src_path.file_name().expect("Couldn't get library filename");
      let dest_path = dest_dir.join(src_name);
      copy_file(src_path, &dest_path)?;
      continue;
    } else if framework.contains('/') {
      return Err(anyhow::anyhow!(
        "Framework path should have .framework extension: {}",
        framework
      ));
    }
    if let Some(home_dir) = dirs::home_dir() {
      if copy_framework_from(&home_dir.join("Library/Frameworks/"), framework, dest_dir)? {
        continue;
      }
    }
    if copy_framework_from("/Library/Frameworks/".as_ref(), framework, dest_dir)?
      || copy_framework_from("/Network/Library/Frameworks/".as_ref(), framework, dest_dir)?
    {
      continue;

View on GitHub (pinned to 460ec35447)