tauri-apps/tauri · error

Library not found

Error message

Library not found: {}

What it means

When copying macOS frameworks, a `bundle.macOS.framework` entry ending in .dylib is treated as a direct library path; if that path does not exist on disk, copy_frameworks fails with 'Library not found'.

Solutions

  1. Verify the dylib path in `bundle.macOS.frameworks` and correct it
  2. Build/copy the dylib to that location before `tauri build`
  3. If the library comes from another crate, add a build-order dependency or use cargo artifact dependencies

Example fix

// before
"frameworks": ["../target/libs/libfoo.dylib"]  // never built
// after
"frameworks": ["${PROJECT_DIR}/libs/libfoo.dylib"]  // ensure file exists
Defensive patterns

Strategy: validation

Validate before calling

for (const fw of cfg.bundle?.macOS?.frameworks ?? []) {
  if (fw.endsWith('.dylib') && !fs.existsSync(fw)) throw new Error(`dylib missing: ${fw}`);
}

Type guard

const dylibExists = (p: string): p is string => p.endsWith('.dylib') && fs.existsSync(p);

Try / catch

try {
  await buildMac();
} catch (e) {
  if (String(e).includes('Library not found')) throw new Error(`Build or correct dylib path: ${e.message}`);
  throw e;
}

Prevention

When it happens

Trigger: `tauri.conf.json` `bundle.macOS.frameworks` contains a `*.dylib` path that is missing at build time (try_build -> copy_frameworks).

Common situations: Dylib built in a previous step that failed or was cleaned, wrong relative/absolute path, or building macOS bundle on CI where the native library wasn't compiled.

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


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

Appendix: 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 460ec35447)