tauri-apps/tauri · error · anyhow::Error

Library not found: {}

Error message

Library not found: {}

What it means

On macOS, tauri-build processes each entry of bundle.macOS.frameworks: entries ending in .framework are copied as directories, and entries ending in .dylib are treated as literal file paths. This error fires when a .dylib entry's path does not exist on disk before copy_file runs.

Source

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

}

// 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)?

View on GitHub (pinned to 2f1cd75b0f)

Solutions

  1. Fix the path in tauri.conf.json so it resolves to the existing .dylib file
  2. Generate/compile the dylib before tauri build (hook it into beforeBuildCommand if it is a build artifact)
  3. If you meant a system-installed framework, use a bare name (no slash) or a .framework path instead of a .dylib path

Example fix

// before
"macOS": { "frameworks": ["lib/native/libmylib.dylib"] }  // file missing

// after
"macOS": { "frameworks": ["libs/libmylib.dylib"] }  // path exists
Defensive patterns

Strategy: validation

Validate before calling

# prebuild check: every .dylib frameworks entry must exist
for p in $(jq -r '.bundle.macOS.frameworks[]?' src-tauri/tauri.conf.json 2>/dev/null | grep '\.dylib$'); do
  [ -f "src-tauri/$p" ] || echo "missing dylib: $p"
done

Prevention

When it happens

Trigger: Building on macOS with bundle.macOS.frameworks containing a '.dylib'-suffixed path (relative or absolute) that is not present at build time - typo'd path, dylib produced by another crate or prebuild step that never ran, or path relative to the wrong working directory.

Common situations: Linking a dylib built by a workspace crate whose build step hasn't run; absolute paths valid on one machine but not CI; moving dylibs without updating tauri.conf.json.

Related errors


AI-assisted analysis of tauri-apps/tauri@2f1cd75b0f (2026-08-16). Data as JSON: /api/errors/f3a4be779ce5cf14. Report an issue: GitHub.