tauri-apps/tauri · error

Framework path should have .framework extension

Error message

Framework path should have .framework extension: {}

What it means

macOS framework entries in `bundle.macOS.frameworks` must either be a `.framework` bundle path, a `.dylib`, or a bare framework name resolvable in standard Library/Frameworks directories. A value containing '/' that is not one of the handled forms is rejected with this error.

Solutions

  1. Change the entry to end with `.framework` (the bundle directory) or `.dylib`
  2. Use just the framework name (e.g. "Sparkle") so tauri resolves it from ~/Library/Frameworks or /Library/Frameworks
  3. Remove the stray path if the framework should come from system search paths

Example fix

// before
"frameworks": ["libs/Sparkle"]
// after
"frameworks": ["libs/Sparkle.framework"]
Defensive patterns

Strategy: validation

Validate before calling

for (const fw of cfg.bundle?.macOS?.frameworks ?? []) {
  if (fw.includes('/') && !fw.endsWith('.framework') && !fw.endsWith('.dylib')) {
    throw new Error(`Framework entry must be *.framework or *.dylib: ${fw}`);
  }
}

Type guard

const isValidFrameworkEntry = (fw: string) => !fw.includes('/') || fw.endsWith('.framework') || fw.endsWith('.dylib');

Try / catch

try {
  await buildMac();
} catch (e) {
  if (String(e).includes('.framework extension')) throw new Error(`Fix frameworks entry format: ${e.message}`);
  throw e;
}

Prevention

When it happens

Trigger: An entry in `bundle.macOS.frameworks` contains a slash (looks like a path) but does not end with `.framework` or `.dylib`, so copy_frameworks cannot classify it.

Common situations: Typo like `libs/Foo.framewrk`, pointing at the binary inside a framework bundle (`Foo.framework/Foo`), or an outdated config from a different bundler convention.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

    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;
    }
  }
  Ok(())
}

View on GitHub (pinned to 460ec35447)