# Tauri 2.0 Error Resolution Guide — Part 1: Build, Config & Plugin Errors > **Version**: 2.0 | **Last Updated**: 2026-05-31 > **Official Docs**: https://v2.tauri.app > > This file covers Categories A-H (build-time and configuration errors). Part 2 covers runtime, platform, mobile errors and best practices. --- ## Table of Contents 1. [Category A: Rust Compilation Errors (Cargo Build)](#category-a-rust-compilation-errors-cargo-build) 2. [Category B: v1→v2 Migration Compile Errors](#category-b-v1v2-migration-compile-errors) 3. [Category C: Async Command & Thread Safety Errors](#category-c-async-command--thread-safety-errors) 4. [Category D: Configuration (`tauri.conf.json`) Errors](#category-d-configuration-tauriconfjson-errors) 5. [Category E: Capabilities & Permission Errors](#category-e-capabilities--permission-errors) 6. [Category F: Plugin Integration Errors](#category-f-plugin-integration-errors) 7. [Category G: IPC / Command Runtime Errors](#category-g-ipc--command-runtime-errors) 8. [Category H: Webview & Window Runtime Errors](#category-h-webview--window-runtime-errors) **See also**: [Part 2: Runtime, Platform & Mobile Errors](./02-runtime-platform-mobile-errors.md) --- ## Category A: Rust Compilation Errors (Cargo Build) ### A1. `tauri` and `tauri-build` Version Mismatch **Error:** ``` failed to get cargo metadata: cargo metadata command exited with a non zero exit code: error: failed to parse manifest ``` **Cause:** Mixed v1 and v2 dependencies in `Cargo.toml`. The `tauri` and `tauri-build` crate versions don't match, or old plugin dependencies remain from v1. **Solution:** Ensure all `tauri-*` dependencies are on v2. Run `cargo update` in `src-tauri/`: ```toml [build-dependencies] tauri-build = { version = "2", features = [] } [dependencies] tauri = { version = "2", features = [] } tauri-plugin-opener = "2" # NOT "1" ``` Then: `cd src-tauri && cargo update` --- ### A2. Rust Edition 2024 Incompatibility **Error:** Cargo.toml resolution errors or crate compilation failures with no clear error message. **Cause:** Tauri 2.0 is **incompatible** with Rust Edition 2024 due to a dependency on the `cargo_toml` crate (specified as `^0.19`). **Solution:** Use `edition = "2021"` in `Cargo.toml` — do NOT switch to edition 2024: ```toml [package] edition = "2021" # Required — edition 2024 will NOT work ``` --- ### A3. Missing `#[lib]` Section in Cargo.toml **Error:** ``` error: `src-tauri/src/lib.rs` not found ``` or linker errors on mobile platforms. **Cause:** Tauri 2.0 requires a `lib.rs` entry-point. The `Cargo.toml` must declare a `[lib]` section with the correct crate types for mobile support. **Solution:** Add to `Cargo.toml`: ```toml [lib] name = "my_app_lib" crate-type = ["staticlib", "cdylib", "rlib"] ``` Create `src-tauri/src/lib.rs` with your core logic in `pub fn run()`, and a minimal `main.rs` that calls `my_app_lib::run()`. > **Naming convention:** The `[lib]` `name` field must match the crate name used in `main.rs`'s function call (`crate_name::run()`). Rust replaces hyphens with underscores in crate identifiers, so a `name = "my-app-lib"` in Cargo.toml becomes `my_app_lib` in code — your `main.rs` must call `my_app_lib::run()`, not `my-app-lib::run()`. Keep this naming consistent across `[lib]`, `main.rs`, and any `mod` re-exports. --- ### A4. `windres` Not Found (Windows) **Error:** ``` error: Couldn't execute windres to compile Windows resource file (.rc) ``` **Cause:** Missing the Windows resource compiler, which is part of the MinGW or MSVC build tools. **Solution:** Install Visual Studio Build Tools with the "Desktop development with C++" workload. Ensure `rc.exe` and `windres` are on your system PATH. Alternatively, install the full Visual Studio IDE. --- ### A5. `strip` Fails on Linux **Error:** ``` error: Calling strip on library ... failed ``` **Cause:** Incompatible or missing `strip` binary on Linux (particularly Arch-based distros). **Solution:** Install GNU binutils: ```bash sudo pacman -S binutils # Arch sudo apt install binutils # Debian/Ubuntu sudo dnf install binutils # Fedora ``` --- ### A6. Windows `windows` Crate Compilation Hangs **Error:** Build hangs silently at "Compiling windows v0.61.x" with no progress. **Cause:** Two common causes: 1. **Trend Micro** (or similar antivirus) "Unauthorized Change Prevention" blocking `rustc.exe` 2. Feature unification causing hundreds of Win32 API features to activate, making compilation extremely slow **Solution:** 1. Temporarily disable Trend Micro or add an exception for the project directory 2. Reduce parallel jobs: `set CARGO_BUILD_JOBS=1` 3. Optimize dev build for the `windows` crate: ```toml [profile.dev.package.windows] opt-level = 1 ``` --- ### A7. Build Terminates Silently Mid-Build **Error:** `cargo build` stops at ~50% with no error output. **Cause:** Antivirus interference, out-of-memory, or corrupted build cache. **Solution:** 1. Clear build cache: `cd src-tauri && cargo clean` 2. Temporarily disable antivirus 3. Reduce parallel jobs: `CARGO_BUILD_JOBS=1` 4. Check disk space and available RAM --- ### A8. `STATUS_ACCESS_VIOLATION` During Compilation (Windows) **Error:** ``` STATUS_ACCESS_VIOLATION ``` Segfault during the build process. **Cause:** Corrupted toolchain, incompatible library version, or memory issue. **Solution:** 1. Update Rust toolchain: `rustup update` 2. Clean and rebuild: `cd src-tauri && cargo clean && cargo build` 3. If persistent, reinstall Rust: `rustup self uninstall && rustup-init` --- ## Category B: v1→v2 Migration Compile Errors ### B1. `tauri::api` Module Removed **Error:** ``` error[E0432]: unresolved import `tauri::api` ``` or `error[E0412]: cannot find module 'api' in 'tauri'` **Cause:** Tauri 2.0 completely removed `tauri::api`. Every sub-module was moved to plugins. **Solution:** Replace each sub-module: ```rust // ❌ v1 — all of these are REMOVED use tauri::api::dialog; use tauri::api::http; use tauri::api::fs; use tauri::api::path; use tauri::api::process::Command; use tauri::api::shell; use tauri::api::version; // ✅ v2 — use plugins or std // dialog → tauri-plugin-dialog // http → tauri-plugin-http // fs → std::fs (Rust) or tauri-plugin-fs (JS) // path → tauri::Manager::path() // process/shell → tauri-plugin-shell // version → semver crate ``` --- ### B2. `Window` Type Renamed to `WebviewWindow` **Error:** ``` error[E0412]: cannot find type `Window` in `tauri` error[E0433]: failed to resolve: use of undeclared type `Window` ``` **Cause:** The `Window` type was renamed throughout Tauri 2.0. **Solution:** ```rust // ❌ v1 let window: tauri::Window = app.get_window("main").unwrap(); let builder = tauri::WindowBuilder::new(&app, "main", tauri::WindowUrl::App("index.html".into())); // ✅ v2 let window: tauri::WebviewWindow = app.get_webview_window("main").unwrap(); let builder = tauri::WebviewWindowBuilder::new(&app, "main", tauri::WebviewUrl::App("index.html".into())); ``` --- ### B3. `SystemTray` / `Menu` APIs Removed **Error:** ``` error[E0412]: cannot find type `SystemTray` in `tauri` error[E0412]: cannot find type `Menu` in `tauri` error[E0412]: cannot find type `CustomMenuItem` in `tauri` error[E0412]: cannot find type `Submenu` in `tauri` ``` **Cause:** All menu and tray types were refactored into sub-modules using the `muda` crate. **Solution:** ```rust // ❌ v1 let menu = tauri::Menu::with_items(app, items)?; let item = tauri::CustomMenuItem::new("id", "Label"); let tray = tauri::SystemTray::new(); // ✅ v2 use tauri::menu::{MenuBuilder, MenuItemBuilder, PredefinedMenuItem, SubmenuBuilder}; use tauri::tray::TrayIconBuilder; let menu = MenuBuilder::new(app) .item(MenuItemBuilder::with_id("toggle", "Toggle").build(app)?) .build(app)?; let tray = TrayIconBuilder::with_id("my-tray") .menu(&menu) .on_menu_event(|app, event| { /* handle */ }) .on_tray_icon_event(|tray, event| { /* handle */ }) .build(app)?; ``` --- ### B4. `App::clipboard_manager` / `get_cli_matches` / `global_shortcut_manager` Removed **Error:** ``` error[E0599]: no method named 'clipboard_manager' found error[E0599]: no method named 'get_cli_matches' found error[E0599]: no method named 'global_shortcut_manager' found error[E0599]: no method named 'fs_scope' found ``` **Cause:** These methods were moved to their respective plugins. **Solution:** ```rust // ❌ v1 app.clipboard_manager().write_text("text"); app.get_cli_matches(); app.global_shortcut_manager().register("Ctrl+K", || {}); Manager::fs_scope(&app); // ✅ v2 // Add plugin to Cargo.toml: tauri-plugin-clipboard-manager = "2" use tauri_plugin_clipboard_manager::ClipboardExt; app.clipboard().write_text("text".into()).unwrap(); // Add plugin: tauri-plugin-cli = "2" use tauri_plugin_cli::CliExt; let matches = app.cli().matches(); // Add plugin: tauri-plugin-global-shortcut = "2" use tauri_plugin_global_shortcut::GlobalShortcutExt; app.global_shortcut().on_shortcuts("Ctrl+K", |_| {}); // FS scope use tauri_plugin_fs::FsExt; // scope is now accessed via FsExt trait ``` --- ### B5. `tauri::updater` Module Removed **Error:** ``` error[E0432]: unresolved import `tauri::updater` ``` **Cause:** The updater was extracted into a plugin. The built-in auto-update dialog was also removed. **Solution:** Add `tauri-plugin-updater = "2"` to `Cargo.toml`. The updater no longer has an automatic dialog — you must implement update checking and installation manually: ```rust use tauri_plugin_updater::UpdaterExt; // Check for updates let update = app.updater().check().await?; if update.is_update_available() { update.download_and_install(|chunk, content_len, received| { // Progress callback }, || { // Install callback }).await?; } ``` --- ### B6. Cargo Feature Names Changed **Error:** ``` error[E0557]: feature `shell-open-api` is not included error[E0557]: feature `process-command-api` is not included error[E0557]: feature `system-tray` is not included error[E0557]: feature `updater` is not included ``` **Cause:** Several Cargo features were renamed or removed in v2. **Solution:** ```toml # ❌ v1 features (REMOVED) features = ["shell-open-api", "process-command-api", "system-tray", "updater"] # ✅ v2 — use plugins instead: # shell-open-api → tauri-plugin-shell # process-command-api → tauri-plugin-shell # system-tray → renamed to "tray-icon" feature # updater → tauri-plugin-updater ``` --- ### B7. JavaScript Import Path Changes **Error:** ``` Module not found: @tauri-apps/api/tauri ``` **Cause:** The `@tauri-apps/api/tauri` module was renamed to `@tauri-apps/api/core` in v2. **Solution:** ```javascript // ❌ v1 import { invoke } from '@tauri-apps/api/tauri'; import { Window } from '@tauri-apps/api/window'; import { open } from '@tauri-apps/api/dialog'; import { readFile } from '@tauri-apps/api/fs'; // ✅ v2 import { invoke } from '@tauri-apps/api/core'; import { WebviewWindow } from '@tauri-apps/api/webviewWindow'; import { open } from '@tauri-apps/plugin-dialog'; import { readFile } from '@tauri-apps/plugin-fs'; ``` --- ## Category C: Async Command & Thread Safety Errors ### C1. Borrowed Arguments in Async Commands **Error:** ``` error[E0757]: `value` has lifetime `'a` that is not constrained by the fn body ``` Or generic lifetime errors. **Cause:** Async commands are executed via `async_runtime::spawn`, which requires `'static` lifetimes. Borrowed types like `&str`, `&Path` cannot be used directly. **Solution — Option A:** Convert to owned types: ```rust // ❌ WRONG #[tauri::command] async fn process(data: &str) -> String { some_async_fn().await; data.to_string() } // ✅ CORRECT — use owned String #[tauri::command] async fn process(data: String) -> String { some_async_fn().await; data } ``` **Solution — Option B:** Wrap return in `Result`: ```rust #[tauri::command] async fn process(data: &str) -> Result { some_async_fn().await; Ok(data.to_string()) } ``` --- ### C2. `std::sync::Mutex` Not `Send` Across `.await` **Error:** ``` error[E0277]: `MutexGuard>` cannot be sent between threads safely ``` **Cause:** Tauri's async runtime is multi-threaded. `std::sync::MutexGuard` is NOT `Send`, so holding a lock across an `.await` point causes a compile error. **Solution:** Use `tokio::sync::Mutex` instead: ```rust // ❌ WRONG — std::sync::MutexGuard is not Send use std::sync::Mutex; #[tauri::command] async fn process(state: State<'_, Mutex>) { let guard = state.lock().unwrap(); some_async_fn().await; // ERROR here! } // ✅ CORRECT — tokio::sync::MutexGuard IS Send use tokio::sync::Mutex; #[tauri::command] async fn process(state: State<'_, Mutex>) { let guard = state.lock().await; some_async_fn().await; // OK! } ``` --- ### C3. `std::sync::RwLock` Not `Send` Across `.await` **Error:** ``` error[E0277]: `RwLockReadGuard` cannot be sent between threads safely ``` **Cause:** Same as C2 but with `RwLock`. `std::sync::RwLockReadGuard` / `RwLockWriteGuard` is NOT `Send`. **Solution:** Use `tokio::sync::RwLock` for async contexts: ```rust // ❌ WRONG use std::sync::RwLock; let guard = state.read().unwrap(); some_async_fn().await; // ✅ CORRECT use tokio::sync::RwLock; let guard = state.read().await; some_async_fn().await; ``` --- ### C4. Non-`Send` Types (`Rc`, `RefCell`) in Async Commands **Error:** ``` error[E0277]: `Rc` cannot be sent between threads safely error[E0277]: `RefCell` cannot be sent between threads safely ``` **Cause:** `Rc`, `RefCell`, and `Cell` are not `Send`. They cannot exist across `.await` points in Tauri's multi-threaded async runtime. **Solution:** Replace with thread-safe alternatives: ```rust // ❌ WRONG use std::rc::Rc; use std::cell::RefCell; // ✅ CORRECT use std::sync::Arc; // Instead of Rc use tokio::sync::Mutex; // Instead of RefCell use std::sync::atomic::{AtomicUsize, Ordering}; // Instead of Cell for primitives ``` --- ## Category D: Configuration (`tauri.conf.json`) Errors ### D1. V1 Config Keys in V2 Project **Error:** ``` Error: tauri.conf.json error on `build`: Additional properties are not allowed ('devPath', 'distDir' were unexpected) ``` **Cause:** Using v1 config key names (`devPath`, `distDir`) in a v2 project. **Solution:** ```json // ❌ v1 { "build": { "devPath": "http://localhost:1420", "distDir": "../dist" } } // ✅ v2 { "build": { "devUrl": "http://localhost:1420", "frontendDist": "../dist" } } ``` --- ### D2. V1 `allowlist` Key Not Recognized **Error:** ``` Error: tauri.conf.json error: Additional properties are not allowed ('allowlist' was unexpected) ``` **Cause:** The v1 `allowlist` was completely replaced by the capabilities/permissions ACL system in v2. **Solution:** Remove `allowlist` entirely from `tauri.conf.json`. Create capability files in `src-tauri/capabilities/`: ```json { "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "windows": ["main"], "permissions": ["core:default", "fs:default", "dialog:default"] } ``` --- ### D3. V1 `tauri` Section Instead of `app` **Error:** ``` Error: tauri.conf.json error: Additional properties are not allowed ('tauri' was unexpected) ``` **Cause:** The top-level `tauri` section was renamed to `app` in v2. **Solution:** ```json // ❌ v1 { "tauri": { "windows": [...], "security": {...} } } // ✅ v2 { "app": { "windows": [...], "security": {...} } } ``` --- ### D4. `beforeDevCommand` Terminated with Non-Zero Status **Error:** ``` Error: The "beforeDevCommand" terminated with a non-zero status code. ELIFECYCLE Command failed with exit code 1. ``` **Cause:** The npm script referenced in `beforeDevCommand` fails. Common causes: wrong port, missing dependency, or port conflict. **Solution:** 1. Verify `beforeDevCommand` matches an actual script in `package.json` 2. Ensure ports match between `devUrl` and your actual dev server 3. Check that all npm dependencies are installed: `npm install` --- ### D5. `frontendDist` Points to Wrong Directory **Error:** ``` AssetNotFound("index.html") ``` Or a blank white screen in production builds. **Cause:** `build.frontendDist` points to a directory that doesn't contain the built frontend output. **Solution:** Verify your bundler's output directory matches `frontendDist`: | Framework | Default Output | `frontendDist` | |-----------|---------------|-----------------| | Vite | `dist/` | `../dist` | | Next.js (export) | `out/` | `../out` | | SvelteKit (static) | `build/` | `../build` | | CRA | `build/` | `../build` | --- ### D6. `tauri.conf.json` Not Found on Mobile Dev **Error:** ``` Couldn't recognize the current folder as a Tauri project. It must contain a 'tauri.conf.json' ``` **Cause:** The project uses `tauri.config.json` (also valid) but the mobile subcommand doesn't handle both names correctly. **Solution:** Rename to `tauri.conf.json`: ```bash mv src-tauri/tauri.config.json src-tauri/tauri.conf.json ``` --- ## Category E: Capabilities & Permission Errors ### E1. Plugin Command Not Allowed — "Plugin Not Found" **Error:** ``` dialog.open not allowed. Plugin not found fs.create not allowed. Plugin not found http.request not allowed. Plugin not found ``` **Cause:** **The #1 most common Tauri v2 error.** The plugin may be installed in Rust and JS, but no capability file grants permission for its commands. **Solution:** Add permissions to `src-tauri/capabilities/default.json`: ```json { "identifier": "default", "windows": ["main"], "permissions": [ "dialog:default", "fs:default", "http:default" ] } ``` Or use the CLI to auto-generate: `npx tauri add dialog` (this creates the capability file for you). --- ### E2. `event.listen not allowed. Command not found` **Error:** ``` event.listen not allowed. Command not found ``` **Cause:** Even core event functions require permission in v2. **Solution:** Add event permissions: ```json { "permissions": [ "core:event:default" ] } ``` Or be specific: `"core:event:allow-listen"`, `"core:event:allow-emit"`. --- ### E3. `Path not allowed on the configured scope` **Error:** ``` Path not allowed on the configured scope PermissionDenied forbidden path ``` **Cause:** The FS plugin enforces scope-based path restrictions. By default, only specific directories are accessible. **Solution:** Add scope permissions: ```json { "identifier": "fs-scope-capability", "windows": ["main"], "permissions": [ { "identifier": "fs:allow-read", "allow": [{ "path": "$HOME/**" }, { "path": "$APPDATA/**" }] }, { "identifier": "fs:allow-write", "allow": [{ "path": "$APPDATA/**" }] } ] } ``` Available scope variables: `$APPDATA`, `$HOME`, `$APPCONFIG`, `$APPCACHE`, `$APPLOG`, `$RESOURCE`, `$EXE`. --- ### E4. `webview.close not allowed` Despite Permission Being Set **Error:** ``` webview.close not allowed ``` Persists even after adding `webview:allow-close` to capabilities. **Cause:** The capability file is malformed, or the permission identifier string doesn't exactly match what the plugin expects. **Solution:** Verify the exact permission identifier from the plugin's documentation or generated schema. Ensure the `windows` array contains the correct window label. --- ### E5. Permissions Work in Dev But Fail in Build **Error:** Permission/ACL errors only appear after `npm run tauri build`, not during `npm run tauri dev`. **Cause:** Dev mode may run in a less restrictive context. Production builds enforce strict ACL validation. **Solution:** Always test capabilities in a production build. Verify all capability files are in `src-tauri/capabilities/` and properly referenced. --- ### E6. PluginInitialization Error with Old Config **Error:** ``` error while running tauri application: PluginInitialization("http", "invalid type: map, expected unit") ``` **Cause:** Using v1-style `plugins` configuration with `scope` maps in `tauri.conf.json`. **Solution:** Remove old config from `tauri.conf.json`: ```json // ❌ REMOVE THIS from tauri.conf.json { "plugins": { "http": { "scope": ["http://my.api.host/*"] } } } ``` Use the v2 capabilities system instead (see E3). --- ### E7. `program not allowed on the configured shell scope` **Error:** ``` program not allowed on the configured shell scope ``` **Cause:** The shell plugin restricts which programs can be executed via scope configuration. **Solution:** Add the program to the shell scope: ```json { "identifier": "shell-capability", "windows": ["main"], "permissions": [ { "identifier": "shell:allow-execute", "allow": [ { "name": "git", "args": true }, { "name": "node", "args": true }, { "name": "python3", "args": true } ] }, { "identifier": "shell:allow-spawn", "allow": [ { "name": "my-sidecar", "sidecar": true } ] } ] } ``` --- ## Category F: Plugin Integration Errors ### F1. Plugin Not Registered in Builder **Error:** Generic "command not found" or "plugin not found" when using any plugin API. **Cause:** The plugin crate is added to `Cargo.toml` but not registered in the `tauri::Builder`. **Solution:** Every plugin requires `.plugin()` registration: ```rust // ❌ WRONG — plugin installed but not registered tauri::Builder::default() .run(tauri::generate_context!()) // ✅ CORRECT — all plugins registered tauri::Builder::default() .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_http::init()) .run(tauri::generate_context!()) ``` --- ### F2. `tauri-plugin-process` — `request_restart` Not Found **Error:** ``` error[E0599]: no method named 'request_restart' found for struct 'AppHandle' ``` **Cause:** In Tauri 2.0, `exit()` and `restart()` are core API methods, not plugin methods. **Solution:** Use the core API directly: ```rust // ❌ WRONG app.handle().process().restart(); // ✅ CORRECT — core API app_handle.restart(); app_handle.exit(0); ``` --- ### F3. SQL Plugin Top-Level-Await Error (Webpack) **Error:** ``` ERROR in ./src/App.js: Module parse failed: The top-level-await experiment is not enabled ``` **Cause:** The SQL plugin's JS import uses top-level await, which requires bundler configuration changes. **Solution:** Enable in webpack config: ```javascript // webpack.config.js module.exports = { experiments: { topLevelAwait: true } }; ``` Or use dynamic imports instead of static imports. --- ### F4. `tauri-cli v2.9.0` Compilation Failure **Error:** ``` error[E0412]: cannot find type 'Error' in crate 'tauri_macos_sign' ``` **Cause:** Version-specific bug in tauri-cli. **Solution:** Use a different CLI version or update to the latest: ```bash npm install @tauri-apps/cli@latest ``` --- ### F5. App Unresponsive After Plugin Dialog Calls **Error:** App freezes/becomes unresponsive with no error message. **Cause:** Dialog plugin calls can block the main thread on some platforms by competing for the same Windows message loop. **Solution:** Ensure plugin calls are async. Avoid calling multiple dialog operations simultaneously. Update to the latest plugin version. --- ## Category G: IPC / Command Runtime Errors ### G1. Command Not Found at Runtime **Error:** ``` Error: command not found ``` (from frontend JS `invoke()` call) **Cause:** The Rust command function exists but is **not registered** in `generate_handler![]`. **Solution:** ```rust // ❌ WRONG — command exists but not registered #[tauri::command] fn my_command() -> String { "hello".into() } tauri::Builder::default() .invoke_handler(tauri::generate_handler![some_other_command]) // missing! // ✅ CORRECT tauri::Builder::default() .invoke_handler(tauri::generate_handler![my_command, some_other_command]) ``` --- ### G2. Only Last `invoke_handler` Takes Effect **Error:** Some commands silently don't work — only commands in the last `invoke_handler` call work. **Cause:** Calling `.invoke_handler()` multiple times — each call **overwrites** the previous one. **Solution:** Pass ALL commands in a single call: ```rust // ❌ WRONG — second call overwrites first .invoke_handler(tauri::generate_handler![cmd_a]) .invoke_handler(tauri::generate_handler![cmd_b]) // ✅ CORRECT .invoke_handler(tauri::generate_handler![cmd_a, cmd_b]) ``` --- ### G3. `pub` on Commands in `lib.rs` Causes Multiple Definition Error **Error:** ``` error[E0255]: the name '__cmd__my_command' is defined multiple times ``` **Cause:** The `#[tauri::command]` macro generates a companion item named `__cmd__` in the same scope. When a command in `lib.rs` is marked `pub`, the generated `__cmd__` glue item is also `pub` — and since `lib.rs` itself re-exports everything at the crate root, the command's `__cmd__` symbol collides with a second copy that `generate_handler![]` produces internally. This can also happen when the same command function appears in multiple modules (e.g., defined in one module and `pub use`'d into another). **Solution:** Remove `pub` from commands in `lib.rs`, or move them to a separate module where they MUST be `pub`: ```rust // In lib.rs — do NOT use pub #[tauri::command] fn my_command() -> String { /* ... */ } // In commands.rs — MUST use pub #[tauri::command] pub fn my_command() -> String { /* ... */ } ``` --- ### G4. Error Types Don't Implement `Serialize` **Error:** ``` error[E0277]: `std::io::Error` doesn't implement `serde::Serialize` ``` **Cause:** Standard library error types don't implement `Serialize`, which Tauri requires for crossing the IPC boundary. **Solution:** Create a custom error type: ```rust #[derive(Debug, thiserror::Error)] enum AppError { #[error("IO error: {0}")] Io(#[from] std::io::Error), #[error("Network error: {0}")] Network(#[from] reqwest::Error), } impl serde::Serialize for AppError { fn serialize(&self, serializer: S) -> Result where S: serde::ser::Serializer { serializer.serialize_str(self.to_string().as_ref()) } } ``` --- ### G5. `window.__TAURI__` Not Defined **Error:** ``` ReferenceError: __TAURI__ is not defined ``` **Cause:** (1) Running frontend code outside the Tauri webview (browser/SSR). (2) `withGlobalTauri` not set to `true`. (3) Code runs before Tauri injects IPC. **Solution:** 1. For bundled apps: use `import { invoke } from '@tauri-apps/api/core'` 2. For vanilla JS: set `"app": { "withGlobalTauri": true }` in `tauri.conf.json` 3. Never run Tauri API code in SSR (Next.js server components) 4. Wrap calls in DOMContentLoaded or wait for `tauri://ready` event --- ### G6. Tauri 2.0.2 UTF-8 Payload Breaking Change **Error:** Invoke calls break with encoding errors after upgrading to Tauri 2.0.2. **Cause:** Tauri 2.0.2 introduced strict UTF-8 validation on invoke payloads. Non-UTF-8 data now causes errors. **Solution:** Base64-encode all binary data before passing through invoke. Pin Tauri versions in `Cargo.toml` to prevent surprise upgrades. --- ## Category H: Webview & Window Runtime Errors ### H1. `failed to create webview: WebView2 error` **Error:** ``` error while running tauri application: Runtime(CreateWebview(WebView2Error(WindowsError(Error { code: 0x80070057, message: "The parameter is incorrect." })))) ``` Or `0x800700AA` ("The requested resource is in use"). **Cause:** Multiple possible causes: (1) WebView2 runtime not installed/corrupted, (2) Invalid `additional_browser_args`, (3) Another process holding a WebView2 lock, (4) Data folder creation failure. **Solution:** 1. Install/repair WebView2 runtime: - **winget (recommended):** `winget install Microsoft.WebView2Runtime` - **Direct download:** https://developer.microsoft.com/en-us/microsoft-edge/webview2/ - **Evergreen Bootstrapper:** Download and run the bootstrapper from the link above to install/update to the latest version 2. Remove custom `additional_browser_args` from config 3. Kill old Tauri dev instances: `taskkill /f /im .exe` 4. For multi-webview support, ensure `features = ["unstable"]` in Cargo.toml --- ### H2. Blank/Frozen Screen on Additional WebviewWindow **Error:** New window appears as a frozen white screen that cannot be closed. **Cause:** The webview doesn't have a valid URL, capabilities aren't configured for the new window's label, or the webview was created before the parent window was fully ready. **Solution:** ```javascript const { WebviewWindow } = window.__TAURI__.webviewWindow; const webview = new WebviewWindow('unique-label', { url: 'path-to-page.html', title: 'Secondary Window' }); webview.once('tauri://error', (e) => console.error('Window error:', e)); ``` Ensure capabilities include the new window's label. --- ### H3. Cannot Create Child Webview Without Unstable Feature **Error:** Webview creation from JavaScript silently fails. **Cause:** Multi-webview support requires the `unstable` feature flag. **Solution:** Add to `Cargo.toml`: ```toml tauri = { version = "2", features = ["unstable"] } ``` Note: This uses nightly/unstable Rust features. --- ### H4. GDK Main Thread Error (Linux) **Error:** ``` * GDK may only be used from the main thread ``` **Cause:** Some Tauri window API calls on Linux internally use GDK, which must be called from the main thread. **Solution:** Ensure all window operations are dispatched to the main thread. Update to the latest Tauri version — many thread safety fixes have been merged. --- --- **Continue to**: [Part 2: Runtime, Platform & Mobile Errors](./02-runtime-platform-mobile-errors.md)