{"record":{"id":"c34fe476092855b4","repo":"gitbutlerapp/gitbutler","slug":"failed-to-create-window","errorCode":null,"errorMessage":"Failed to create window","messagePattern":"Failed to create window","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/gitbutler-tauri/src/main.rs","lineNumber":120,"sourceCode":"\n        let log = tauri_plugin_log::Builder::default()\n            .target(Target::new(TargetKind::LogDir {\n                file_name: Some(\"ui-logs\".to_string()),\n            }))\n            .level(if tauri_debug_logging {\n                tauri_plugin_log::log::LevelFilter::Debug\n            } else {\n                tauri_plugin_log::log::LevelFilter::Error\n            });\n\n        let builder = tauri::Builder::default()\n            .setup(move |tauri_app| {\n                let window = gitbutler_tauri::window::create(\n                    tauri_app.handle(),\n                    \"main\",\n                    \"index.html\".into(),\n                )\n                .expect(\"Failed to create window\");\n\n                // TODO(mtsgrd): Is there a better way to disable devtools in E2E tests?\n                #[cfg(debug_assertions)]\n                if tauri_app.config().product_name != Some(\"GitButler Test\".to_string()) {\n                    window.open_devtools();\n                }\n\n                let app_handle = tauri_app.handle();\n\n                logs::init(app_handle, &app_log_dir, performance_logging, tokio_debug);\n\n                but_action::cli::auto_fix_broken_but_cli_symlink();\n                inherit_interactive_login_shell_environment_if_not_launched_from_terminal();\n                migrate_projects().ok();\n\n                tracing::info!(\n                    \"system git executable for fetch/push: {git:?}\",\n                    git = gix::path::env::exe_invocation(),","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-tauri/src/main.rs#L102-L138","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","solutions":["Install the platform webview: webkit2gtk 4.1 packages on Linux, WebView2 Runtime on Windows","Run the app inside a graphical session: set DISPLAY/WAYLAND_DISPLAY, or use xvfb-run for automated runs","Ensure the window label 'main' is created exactly once and not already registered","Propagate the tauri::Error with ? - the setup closure already returns Result (see exampleFix)"],"exampleFix":"// before\nlet window = gitbutler_tauri::window::create(tauri_app.handle(), \"main\", \"index.html\".into())\n    .expect(\"Failed to create window\");\n\n// after - surfaces the underlying tauri::Error through setup's Result\nlet window = gitbutler_tauri::window::create(tauri_app.handle(), \"main\", \"index.html\".into())?;","handlingStrategy":"try-catch","validationCode":"// Headless guard for Linux launches\n#[cfg(target_os = \"linux\")]\nfn display_available() -> bool {\n    std::env::var_os(\"DISPLAY\").is_some() || std::env::var_os(\"WAYLAND_DISPLAY\").is_some()\n}\n\n// xvfb-run ./GitButler  # gives CI a virtual display","typeGuard":null,"tryCatchPattern":"// The setup closure returns Result - propagate instead of expect\nlet window = gitbutler_tauri::window::create(tauri_app.handle(), \"main\", \"index.html\".into())?;","preventionTips":["Ship webview prerequisites with installers: webkit2gtk on Linux, WebView2 bootstrapper on Windows","Never launch the GUI app without a display; use xvfb-run in automation","Create each window label exactly once per app instance"],"tags":["tauri","webview","window","startup","linux","windows","panic"],"backgroundTag":"webview-creation-failed","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}