farion1231/cc-switch · critical
error while running tauri application
Error message
error while running tauri application
What it means
This is a Rust panic from `.expect("error while running tauri application")` after `tauri::Builder::build(tauri::generate_context!())` (src-tauri/src/lib.rs:1709). `build()` returns `Result<App, tauri::Error>`, and it errs when Tauri cannot assemble the app at startup: a plugin's `initialize()` failed (this app chains single_instance, deep_link, process, dialog, opener, store, window_state, log, updater), the main window/WebView from tauri.conf.json could not be created, or the `setup` hook aborted. Tauri surfaces it this way because application assembly is treated as unrecoverable: without plugins and a webview the app cannot function. The real cause is appended to the panic message as the `Debug` of `tauri::Error` (e.g. `PluginInitialization("...")` or a WebView creation error) — always read the text after the colon.
Source
Thrown at src-tauri/src/lib.rs:1719
// Workspace files (OpenClaw)
commands::read_workspace_file,
commands::write_workspace_file,
// Daily memory files (OpenClaw workspace)
commands::list_daily_memory_files,
commands::read_daily_memory_file,
commands::write_daily_memory_file,
commands::delete_daily_memory_file,
commands::search_daily_memory_files,
commands::open_workspace_directory,
// lightweight mode (for testing or low-resource environments)
commands::enter_lightweight_mode,
commands::exit_lightweight_mode,
commands::is_lightweight_mode,
]);
let app = builder
.build(tauri::generate_context!())
.expect("error while running tauri application");
app.run(|app_handle, event| {
// 处理退出请求(所有平台)
if let RunEvent::ExitRequested { api, code, .. } = &event {
match classify_exit_request(*code) {
// code 为 None 表示运行时自动触发(如隐藏窗口的 WebView 被回收导致无存活窗口),
// 此时应仅阻止退出、保持托盘后台运行。
ExitRequestAction::StayInTray => {
log::info!("运行时触发退出请求(无存活窗口),阻止退出以保持托盘后台运行");
api.prevent_exit();
return;
}
// code 为 RESTART_EXIT_CODE:app.restart() / 自更新 relaunch 发起的重启。
// 这条路径上 prevent_exit() 会被 Tauri 忽略,事件循环必定退出,随后由
// Tauri 在 RunEvent::Exit 后用新二进制 re-exec(macOS 会按更新后的
// Info.plist 解析可执行名)。
//
// 绝不能复用下面的异步清理任务:该任务在 tokio 线程调 save_window_state,View on GitHub (pinned to 3217f72596)
Solutions
- Read the full panic output first: the text after 'error while running tauri application:' is the Debug of tauri::Error and names the failing subsystem (PluginInitialization("store"), webview creation, etc.) — fix that subsystem, not the expect() line.
- If in a headless/SSH/CI session, give the app a display: `xvfb-run -a cargo tauri dev` or set DISPLAY/WAYLAND_DISPLAY; for tests, prefer this app's lightweight mode instead of launching the full windowed build.
- On Linux, install the WebView runtime deps the binary links against: `sudo apt install libwebkit2gtk-4.1-0 libgtk-3-0` and verify with `ldd target/release/<binary> | grep -i webkit`; on distros with only webkit2gtk-4.0, upgrade or build against 4.0.
- On Windows, install the WebView2 Evergreen Runtime, or set `bundle.webviewInstallMode` to `offlineInstaller`/`embedBootstrapper` in tauri.conf.json so air-gapped machines get a runtime.
- If state corruption or a stale single-instance lock is the cause (app-data dir `~/.local/share/<identifier>`), delete the window-state/store files or call the existing `destroy_single_instance_lock`, then relaunch.
- Replace `.expect` with real Result handling that logs the error before exiting, so production failures carry a clean diagnostic instead of a bare panic (see exampleFix).
Example fix
// before (src-tauri/src/lib.rs:1707)
let app = builder
.build(tauri::generate_context!())
.expect("error while running tauri application");
// after
let app = match builder.build(tauri::generate_context!()) {
Ok(app) => app,
Err(e) => {
eprintln!("failed to start application: {e:#}");
log::error!("tauri build failed: {e:#}");
std::process::exit(1);
}
}; Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight checks before builder.build() (Linux/Unix)
fn environment_ready() -> bool {
#[cfg(target_os = "linux")]
{
if std::env::var_os("DISPLAY").is_none() && std::env::var_os("WAYLAND_DISPLAY").is_none() {
eprintln!("no display server found; set DISPLAY/WAYLAND_DISPLAY or run under xvfb");
return false;
}
}
true
}
if !environment_ready() {
std::process::exit(1);
}
let app = builder.build(tauri::generate_context!()); Type guard
// Narrow the tauri::Error variant to decide recovery vs exit
fn is_plugin_init_error(e: &tauri::Error) -> bool {
matches!(e, tauri::Error::PluginInitialization(_))
} Try / catch
// Rust: never .expect() on build(); match the Result and log {:#} (anyhow-style chain)
let app = match builder.build(tauri::generate_context!()) {
Ok(app) => app,
Err(err) if is_plugin_init_error(&err) => {
log::error!("plugin failed to initialize: {err:#}");
std::process::exit(1);
}
Err(err) => {
log::error!("tauri app build failed: {err:#}");
eprintln!("tauri app build failed: {err:#}");
std::process::exit(1);
}
}; Prevention
- Treat app startup as fallible: handle the Result from build() with logging instead of .expect() so field failures are diagnosable.
- In CI or tests that touch the full app, run under `xvfb-run` or skip window creation; this repo already ships lightweight-mode commands for low-resource environments — use them.
- Ship runtime deps with the bundle: declare webkit2gtk-4.1 deb/rpm dependencies and set Windows `webviewInstallMode` explicitly rather than relying on the online bootstrapper.
- Document the required WebView (WebKit2GTK 4.1 / WebView2) in install instructions and add a smoke test that launches the binary on a clean image.
- Avoid force-killing the app; use its exit path so single-instance locks and window-state/store files are released cleanly (see destroy_single_instance_lock in this codebase).
When it happens
Trigger: Calling `builder.build(tauri::generate_context!())` when: (1) the system cannot create a WebView — Linux without `libwebkit2gtk-4.1-0`/GTK3, Windows without the WebView2 runtime (and the default downloadBootstrapper cannot reach the network), or a headless session with no `DISPLAY`/`WAYLAND_DISPLAY` (SSH, CI, Docker); (2) a plugin fails init — tauri-plugin-store or tauri-plugin-window-state hitting an unwritable/corrupt app-data dir (`~/.local/share/<identifier>`), or an older single-instance plugin version erroring because another instance holds the lock; (3) the `setup` closure (which runs inside `build()` in Tauri v2) panics or a plugin like deep-link/updater fails its initialization with the bundled config.
Common situations: Running `cargo tauri dev` over SSH or in CI without a display server; deploying a raw binary or AppImage to a minimal Linux distro that lacks webkit2gtk 4.1 (Tauri v2 moved from 4.0 to 4.1, so images built for v1 break); Windows Server or stripped Windows without WebView2, or air-gapped machines where the bootstrapper download fails; stale single-instance socket / corrupted window-state or store JSON after a crash or force-kill; Tauri v1→v2 migrations where plugin init order or capabilities changed.
Related errors
- volcengine handled via AK/SK branch above
- ${error}
- Invalid URL
- Skill 存储目录不能与 {app:?} 的 Skills 目录相同: {}
- SKILL_DIRECTORY_CONFLICT
AI-assisted analysis of farion1231/cc-switch@3217f72596 (2026-08-20).
Data as JSON: /api/errors/e4d7b71ffc06481b.
Report an issue: GitHub.