gitbutlerapp/gitbutler · critical

Failed to create window

Error message

Failed to create window

What it means

In the Tauri setup hook, main() creates the 'main' window via gitbutler_tauri::window::create(...) and unwraps with expect("Failed to create window"). create() configures a tauri::WebviewWindowBuilder (fixed label 'main', min size, navigation guard) and returns its build() Result; that fails when the platform webview cannot be created - missing WebView2 runtime on Windows, missing webkit2gtk on Linux, no display on headless Linux - or when a window with the same label already exists.

Source

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

        let log = tauri_plugin_log::Builder::default()
            .target(Target::new(TargetKind::LogDir {
                file_name: Some("ui-logs".to_string()),
            }))
            .level(if tauri_debug_logging {
                tauri_plugin_log::log::LevelFilter::Debug
            } else {
                tauri_plugin_log::log::LevelFilter::Error
            });

        let builder = tauri::Builder::default()
            .setup(move |tauri_app| {
                let window = gitbutler_tauri::window::create(
                    tauri_app.handle(),
                    "main",
                    "index.html".into(),
                )
                .expect("Failed to create window");

                // TODO(mtsgrd): Is there a better way to disable devtools in E2E tests?
                #[cfg(debug_assertions)]
                if tauri_app.config().product_name != Some("GitButler Test".to_string()) {
                    window.open_devtools();
                }

                let app_handle = tauri_app.handle();

                logs::init(app_handle, &app_log_dir, performance_logging, tokio_debug);

                but_action::cli::auto_fix_broken_but_cli_symlink();
                inherit_interactive_login_shell_environment_if_not_launched_from_terminal();
                migrate_projects().ok();

                tracing::info!(
                    "system git executable for fetch/push: {git:?}",
                    git = gix::path::env::exe_invocation(),

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Install the platform webview: webkit2gtk 4.1 packages on Linux, WebView2 Runtime on Windows
  2. Run the app inside a graphical session: set DISPLAY/WAYLAND_DISPLAY, or use xvfb-run for automated runs
  3. Ensure the window label 'main' is created exactly once and not already registered
  4. Propagate the tauri::Error with ? - the setup closure already returns Result (see exampleFix)

Example fix

// before
let window = gitbutler_tauri::window::create(tauri_app.handle(), "main", "index.html".into())
    .expect("Failed to create window");

// after - surfaces the underlying tauri::Error through setup's Result
let window = gitbutler_tauri::window::create(tauri_app.handle(), "main", "index.html".into())?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Headless guard for Linux launches
#[cfg(target_os = "linux")]
fn display_available() -> bool {
    std::env::var_os("DISPLAY").is_some() || std::env::var_os("WAYLAND_DISPLAY").is_some()
}

// xvfb-run ./GitButler  # gives CI a virtual display

Try / catch

// The setup closure returns Result - propagate instead of expect
let window = gitbutler_tauri::window::create(tauri_app.handle(), "main", "index.html".into())?;

Prevention

When it happens

Trigger: Launching the desktop app on a machine without the platform webview: Linux without webkit2gtk installed or without DISPLAY/WAYLAND_DISPLAY (SSH sessions, containers), Windows lacking the WebView2 runtime, or code that creates a second window with the label 'main'.

Common situations: Running the packaged app over SSH or in CI/containers, minimal Linux installs, locked-down Windows Server images without WebView2, and local dev after a system upgrade broke webkit2gtk.

Related errors


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