gitbutlerapp/gitbutler · critical

Failed to build tauri app

Error message

Failed to build tauri app

What it means

`tauri::Builder::build(tauri_context)` assembles the app instance from the compile-time-generated context (tauri.conf.json, bundled assets, plugins) plus every registered plugin's setup. It returns Err when the context is inconsistent with the runtime environment, required assets are missing, or a plugin fails during initialization (for example tauri_plugin_window_state choking on a corrupt state file on non-Linux). The `.expect` aborts process startup, printing the underlying error to stderr.

Source

Thrown at crates/gitbutler-tauri/src/main.rs:421

                        .state::<WindowState>()
                        .remove(window.label());
                }
                tauri::WindowEvent::Focused(focused) if *focused => {
                    window
                        .app_handle()
                        .state::<WindowState>()
                        .flush(window.label())
                        .ok();
                }
                _ => {}
            });

        #[cfg(not(target_os = "linux"))]
        let builder = builder.plugin(tauri_plugin_window_state::Builder::default().build());

        builder
            .build(tauri_context)
            .expect("Failed to build tauri app")
            .run(|_app_handle, _event| {});
    });
    Ok(())
}

/// read all objects, migrate them, and write them back if there was a migration.
fn migrate_projects() -> anyhow::Result<()> {
    for mut project in gitbutler_project::dangerously_list_projects_without_migration()? {
        if let Ok(true) = project.migrate() {
            let (title, git_dir) = (project.title.clone(), project.git_dir().to_owned());
            if let Err(err) = gitbutler_project::update(project.into()) {
                tracing::warn!(
                    "Failed to store migrated project {} at {}: {err}",
                    title,
                    git_dir.display()
                );
            } else {
                tracing::info!("Migrated project {} at {}", title, git_dir.display());

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Read the stderr panic message first — it names the exact underlying cause
  2. Clean rebuild through the tauri CLI (cargo clean, then cargo tauri dev or cargo tauri build) so context and config regenerate together
  3. Delete a corrupt window-state file in the app-data dir if that plugin is implicated
  4. Align tauri and tauri-plugin-* versions in Cargo.toml with the CLI that generated the context

Example fix

// before
builder
    .build(tauri_context)
    .expect("Failed to build tauri app")
    .run(|_app_handle, _event| {});

// after (main returns anyhow::Result)
let app = builder
    .build(tauri_context)
    .context("Failed to build tauri app")?;
app.run(|_app_handle, _event| {});
Defensive patterns

Strategy: validation

Try / catch

match builder.build(tauri_context) {
    Ok(app) => app.run(|_, _| {}),
    Err(e) => {
        eprintln!("failed to build tauri app: {e}");
        std::process::exit(1);
    }
}

Prevention

When it happens

Trigger: Executing `builder.build(tauri_context).expect(...)` at crates/gitbutler-tauri/src/main.rs:421 when the generated context is stale relative to tauri.conf.json, a configured asset is absent from the bundle, or a registered plugin's initialization returns an error.

Common situations: Stale build artifacts after pulling changes that edit tauri.conf.json; building with plain `cargo build` instead of the tauri CLI so context and assets do not match; version skew between tauri crates and the tauri-cli; a corrupt window-state cache.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/a8d4a9dd609411fc. Report an issue: GitHub.