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
- Read the stderr panic message first — it names the exact underlying cause
- Clean rebuild through the tauri CLI (cargo clean, then cargo tauri dev or cargo tauri build) so context and config regenerate together
- Delete a corrupt window-state file in the app-data dir if that plugin is implicated
- 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
- Always generate release builds through the tauri CLI, never bare cargo build
- Clean after editing tauri.conf.json or asset paths
- Keep tauri crate versions locked in step with the CLI
- Ship stderr/log capture so users can report the underlying error
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
- broker already configured
- failed to create app settings
- theme::init() must be called before getting the theme
- failed to create logs dir
- initializing rolling file appender failed
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/a8d4a9dd609411fc.
Report an issue: GitHub.